Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: Apply function to matrix with elements of vector as argument

Suppose I want to apply a function to each row of a matrix. One of the function's arguments takes a vector. I would like to apply the first element of the vector to the first row, the second element to the second row, etc.

For example:

set.seed(123)
df<-matrix(runif(100), ncol=10)

var2 <- c(1:10)

MYFUNC <- function(x, Var=NA){ 
  sum(x)/Var 
}

I tried this:

apply(df, 1, function(x) MYFUNC(x, Var=var2))

But that gives me a 10x10 matrix with the function applied to each row & Var combination, whereas I'm only interested in the diagonal elements. I also looked into the mapply function, but I'm not sure how to apply it in this case.

Any help would be really appreciated.

like image 779
user3640617 Avatar asked Apr 26 '17 20:04

user3640617


2 Answers

Mapply is definitely a possibility. This should work:

mapply(MYFUNC, x = as.data.frame(t(df)), Var = var2)

#V1        V2        V3        V4        V5        V6        V7        V8        V9       V10 
#5.0795111 2.8693537 1.8285747 1.3640238 0.8300597 0.6280441 0.7706310 0.6720132 0.5719003 0.4259674 

The issue I think you were running into is that mapply takes either vectors or lists. In R matrices aren't lists, but data.frames are. All you need to do is transpose your matrix and convert to a data.frame and then mapply should work. Each column in a data.frame is an element in the list which is why we have to transpose it (so that each row will be mapped to each element in the vector).

like image 144
Mike H. Avatar answered Nov 14 '22 21:11

Mike H.


As there are two arguments that should be the corresponding rows and elements in matrix/vector respectively, we can loop through the sequence of rows, subset the data and apply the function

sapply(seq_len(nrow(df)), function(i) MYFUNC(df[i,], Var = var2[i]))
#[1] 5.0795111 2.8693537 1.8285747 1.3640238 0.8300597 0.6280441
#[7] 0.7706310 0.6720132 0.5719003 0.4259674

For the specific example, it can be vectorized with rowSums

rowSums(df)/var2
#[1] 5.0795111 2.8693537 1.8285747 1.3640238 0.8300597 0.6280441 
#[7] 0.7706310 0.6720132 0.5719003 0.4259674
like image 41
akrun Avatar answered Nov 14 '22 21:11

akrun