简体   繁体   中英

R - Apply function with different argument value for each row/column of a matrix

I am trying to apply a function to each row or column of a matrix, but I need to pass a different argument value for each row.

I thought I was familiar with lapply, mapply etc... But probably not enough.

As a simple example :

> a<-matrix(1:100,ncol=10);
> a
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    1   11   21   31   41   51   61   71   81    91
 [2,]    2   12   22   32   42   52   62   72   82    92
 [3,]    3   13   23   33   43   53   63   73   83    93
 [4,]    4   14   24   34   44   54   64   74   84    94
 [5,]    5   15   25   35   45   55   65   75   85    95
 [6,]    6   16   26   36   46   56   66   76   86    96
 [7,]    7   17   27   37   47   57   67   77   87    97
 [8,]    8   18   28   38   48   58   68   78   88    98
 [9,]    9   19   29   39   49   59   69   79   89    99
[10,]   10   20   30   40   50   60   70   80   90   100

Let's say I want to apply a function to each row, I would do :

apply(a, 1, myFunction);

However my function takes an argument, so :

apply(a, 1, myFunction, myArgument);

But if I want my argument to take a different value for each row, I cannot find the right way to do it. If I define a 'myArgument' with multiple values, the whole vector will obviously be passed to each call of 'myFunction'.

I think that I would need a kind of hybrid between apply and the multivariate mapply. Does it make sense ?

One 'dirty' way to achieve my goal is to split the matrix by rows (or columns), use mapply on the resulting list and merge the result back to a matrix :

do.call(rbind, Map(myFunction, split(a,row(a)), as.list(myArgument)));

I had a look at sweep, aggregate, all the *apply variations but I wouldn't find the perfect match to my need. Did I miss it ?

Thank you for your help.

You can use sweep to do that.

a <- matrix(rnorm(100),10)
rmeans <- rowMeans(a)
a_new <- sweep(a,1,rmeans,`-`)
rowMeans(a_new)

I don't think there are any great answers, but you can somewhat simplify your solution by using mapply , which handles the "rbind" part for you, assuming your function always returns the same sizes vector (also, Map is really just mapply ):

a <- matrix(1:80,ncol=8)
myFun <- function(x, y) (x - mean(x)) * y
myArg <- 1:nrow(a)

t(mapply(myFun, split(a, row(a)), myArg))

I know the topic is quiet old but I had the same issue and I solved it that way:

# Original matrix
a <- matrix(runif(n=100), ncol=5)
# Different value for each row
v <- runif(n=nrow(a))
# Result matrix -> Add a column with the row number
o <- cbind(1:nrow(a), a)
fun <- function(x, v) {
  idx <- 2:length(x)
  i <- x[1]
  r <- x[idx] / v[i]
  return(r)
}
o <- t(apply(o, 1, fun, v=v)

By adding a column with the row number to the left of the original matrix, the index of the needed value from the argument vector can be received from the first column of the data matrix.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM