Vectorizing arguments in R

R exists in a funny space between being a functional and procedural language. Unlike languages like LISP, R is perfectly happy to interpret your for loop. This can get you into trouble though, as R treats everything as a list, and it doesn't really have native iterators, like in C++, so looping can be awkard and slow.

But this is one of the first things you learn when you learn R. Don't use for loops. Use the vectorization inherent in the language. If you want 10 random numbers, with each drawn from 10 different distributions (10 means, 10 sds), don't do

  for(i in 1:length(x)){
  x[i] <- rnorm(n=1,mean=meansvec[i],sd=sdvec[i])


x <- rnorm(n=length(x),mean=meansvec,sd=sdvec)

But what if we want 10 draws from each distribution?
One way we could do this would be to write something like

x <- rnorm(n=length(x)*10,
matx <- matrix(x,10,length(x))

But let's look at a slightly trickier case. I wrote this function Muhat to get the precision weighted average of a bunch of data. In math it looks like

$$ \hat{\mu} = \frac{\sum_{j=1}^J \frac{1}{\sigma_j^2+\tau^2}\bar{y}_{.j}}{\sum_{j=1}^{J}\frac{1}{\sigma_j^2+\tau^2}} $$

In R I've written it like this

Muhat <- function(tau,yj,varj){

Looks good, right? The function makes use of vectorization and there are no for loops to be seen.

But what if I want $\hat{\mu}$ for multiple values of $\tau$? I can't just pass a vector of taus to Muhat, because it won't give me the correct answer. There is an implicit assumption in this function that tau is not a vector. One of the simplest options here is to use sapply

muhats <- sapply(tauvector,Muhat,yj=yjvec,varj=varjvec)

This will have the result of calling Muhat once for each element of tauvector, and the call will include all of the named arguments.