I would like to make a list of 2x2 matrices, where each row of a dataframe becomes a 2x2 matrix. I will be working with a huge dataset (toy example for convenience) so I am trying to figure out how to do this without for loops. I have been trying to do this using a homemade function and apply() but I get an error message.
dat<-data.frame(x1=c(2,3,4),
x2=c(1,2,3),
x3=c(5,76,7),
x4=c(4,6,0))
make_matrix<-function(df){
with(dat, matrix(c(x1,x2,x3, x4),byrow=T,nrow=2, ncol=2))
}
apply(dat, 1, FUN=make_matrix)
Error in eval(substitute(expr), data, enclos = parent.frame()) :
numeric 'envir' arg not of length one
We could use asplit
lapply(asplit(dat, 1), matrix, 2, 2, byrow = TRUE)
-output
#[[1]]
# [,1] [,2]
#[1,] 2 1
#[2,] 5 4
#[[2]]
# [,1] [,2]
#[1,] 3 2
#[2,] 76 6
#[[3]]
# [,1] [,2]
#[1,] 4 3
#[2,] 7 0
The OP's function argument and the body is not matching i.e. it takes an argument 'df' and inside the function uses dat
. But, that is not the only issue. When we loop over the row, it is a vector of values and with
will not work on those. As we need a list
, the matrix
can be wrapped in a list
make_matrix <- function(x) list(matrix(x, byrow = TRUE, ncol = 2, nrow = 2))
should work
do.call(c, apply(dat, 1, make_matrix))
#[[1]]
# [,1] [,2]
#[1,] 2 1
#[2,] 5 4
#[[2]]
# [,1] [,2]
#[1,] 3 2
#[2,] 76 6
#[[3]]
# [,1] [,2]
#[1,] 4 3
#[2,] 7 0