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.