Reputation: 107
I am struggling with the "apply" type functions in R. I have a matrix and what I want is to use the elements of each row of the matrix, use a user-defined function to make some calculations based on the input from the matrix, and create a new one that will store the results from these calculations.
I have figured out how to do this when the function returns only one output
So for example assume matrix A and a function that performs some kind of calculation.
> A=matrix(1:16,nrow=4)
> A
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
> B=apply(A,1,FUN=function(x) x[1]**2+2*x[2]+x[3]*x[4])
> B
[1] 128 156 188 224
What I need is to extend this in a case where the output is a vector of more than one elements, imagine for example that I want to calculate the value of three different polynomials instead of one as in the example and obtain again a 4x3 matrix that will contain the calculation of these three polynomials.
For the time being I am doing this with a "for" loop that reads the data row by row, executes the function and stores the results in a new matrix but it is painfully slow. An example is:
A=matrix(1:16,nrow=4)
A
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
calc=function(e1,e2,e3,e4){
x1=e1*e2+3*e3*e4
x2=e4+e2+5*e3**2-e4
x3=e1*e2*e3*e4
return(c(x1,x2,x3))
}
results=matrix(nrow=4,ncol=3)
for (i in 1:4){
k=calc(A[i,1],A[i,2],A[i,3],A[i,4])
results[i,]=k
}
results
[,1] [,2] [,3]
[1,] 356 410 585
[2,] 432 506 1680
[3,] 516 612 3465
[4,] 608 728 6144
Any ideas of how I could apply similar operations to a matrix avoiding the "for" are more than welcome. (I am not constrained to the apply packages)
Upvotes: 0
Views: 650
Reputation: 886938
Not sure if this helps:
fun1 <- function(mat){
x1 <- mat[,1]*mat[,2]+3*mat[,3]*mat[,4]
x2 <- mat[,4]+mat[,2]+5*mat[,3]**2-mat[,4]
x3 <- mat[,1]*mat[,2]*mat[,3]*mat[,4]
cbind(x1,x2,x3)
}
fun1(A)
# x1 x2 x3
# [1,] 356 410 585
# [2,] 432 506 1680
# [3,] 516 612 3465
# [4,] 608 728 6144
Upvotes: 2
Reputation: 3242
Your function doesn't work in the apply framework, because the function should have a vector as its argument, not individual values. If you specify the values within the function it will work:
calc=function(row){
e1 = row[1]; e2 = row[2]; e3 = row[3]; e4 = row[4]
x1=e1*e2+3*e3*e4
x2=e4+e2+5*e3**2-e4
x3=e1*e2*e3*e4
return(c(x1,x2,x3))
}
The apply function will return a full matrix, however it will create this matrix column wise. So the results of the first row will be stored into the first column, etc. This easily solved by taking the transpose of the result.
t(apply(A, 1, calc))
Upvotes: 3
Reputation: 113
apply(A,1,FUN=function(x){
y<-rep(NA,3)
y[1]=x[1]+1
y[2]=x[2]+x[3]
y[3]=x[4]/2
return(t(y))
}
)
That worked for me. Obviously, edit the functions for y[1],y[2],y[3], and if you want more than 3, also edit the line y<-rep(NA,3)
Upvotes: 0