简体   繁体   中英

Using “apply” to apply a function to a matrix where parameters are column-specific

I'm trying to avoid using loops by using apply to apply a user-defined function to a matrix. The problem I have is that there are additional parameters that my function uses and they differ for each column of the matrix. Below is a toy example.

Say I have the following function:

foo <- function(x, a, b, c) return( (a*x + b)^c )

and I want to apply it to a matrix bar using different values of a , b , and c for each column.

bar <- matrix(1:15, ncol = 3)
a <- 4:6
b <- 3:1
c <- 1:3

In this case, for the first column of bar , then a=4 , b=3 , and c=1 . I tried this,

apply(bar, 2, foo, a=a, b=b, c=c)

but this is clearly incorrect, as each column uses all parameters sequentially before wrapping back to the first parameter again. Any suggestions?

We could split the 'bar' by 'column' ( col(bar) ) and with mapply we can apply 'foo' for the corresponding 'a', 'b', 'c' values to each column of 'bar'

mapply(foo, split(bar, col(bar)), a, b, c)

Or without using apply

ind <- col(bar)
(a[ind]*bar +b[ind])^c[ind]

I don't see why you bother with a function at all:

> a <- matrix(4:6,nrow = 5,ncol = 3,byrow = TRUE)
> b <- matrix(3:1,nrow = 5,ncol = 3,byrow = TRUE)
> c <- matrix(1:3,nrow = 5,ncol = 3,byrow = TRUE)
> (a*bar + b)^c
     [,1] [,2]   [,3]
[1,]    7 1024 300763
[2,]   11 1369 389017
[3,]   15 1764 493039
[4,]   19 2209 614125
[5,]   23 2704 753571

I guess that you can just transpose your matrix and use vectorization:

t(foo(t(bar),a,b,c))

This should work for every vectorized foo .

You could put your parameters into the vector:

newbar <- rbind(a,b,c,bar)
newfoo <- function(z){x <- z[-(1:3)]; (z[1]*x+z[2])^z[3]}
apply(newbar,2,newfoo)

which gives

[,1] [,2]   [,3]
    7 1024 300763
   11 1369 389017
   15 1764 493039
   19 2209 614125
   23 2704 753571

You can use sweep ; usually this is for subtracting the mean from each column, but you can pass in an index instead to get parallel indexing across a,b and c:

> sweep(bar, 2, seq_along(a), function(x,i) foo(x, a[i], b[i], c[i]), FALSE)
     [,1] [,2]   [,3]
[1,]    7 1024 300763
[2,]   11 1369 389017
[3,]   15 1764 493039
[4,]   19 2209 614125
[5,]   23 2704 753571

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