How does lapply really work - lapply dcast?
Question
Obviously I still do not understand fully how lapply really works. Sure, it applies a function over list elements and returns a list. Yet when using it with custom functions I am not so sure how to use it efficiently. I want to use it in a custom function that uses dcast for example.
First let's get an example dataset:
df1 <- data.frame(idx=c(rep("a",3),rep("b",3),rep("c",3)),
cat=rep(1:3,3),var1=rnorm(9,0,1)
)
df2 <- data.frame(idx=c(rep("a",4),rep("b",4),rep("c",4)),
cat2=rep(1:4,3),var1=rnorm(12,0,1)
)
mylist <- list(cat=df1,cat2=df2)
library(reshape2)
### result that I want to get just for one data.frame
dcast(df1,idx~cat,value_var="var1")
But I can't get this to go with lapply, I tried:
lapply(mylist,function(x) substitute(dcast(x,idx~x,value_var="var1")))
## returns
$cat
dcast(X[[2L]], idx ~ X[[2L]], value_var = "var1")
Obviously X[[2L]] would not work when evaluating the expression. Further I tried
lapply(names(mylist), function(x) dcast(mylist[[x]],idx~x,value_var="var1" ))
which was working in some similar issue, but caused an error here. Should I use with here?
EDIT: I am surprised that Joshua's answers is exactly what I want. I was on that trail before but dismissed it early when I tried:
test <- function(x){
myformula <- as.formula(paste("idx~",x,sep=""))
myformula
}
test(df2)
## returns
## > idx ~ c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3)
## > <environment: 0x104f0a4d8>
Obviously too early, but can you explain what happens?
Solution
In your first example, x
is an object passed to your function. In the second example, it's a character string. In both cases, it's not a symbol that represents a variable in the data
passed to dcast
.
You need to construct your formula using the name of the list element, so something like this:
# define the function
myfunc <- function(varname) {
# 'varname' is a character string naming the column to use
myformula <- as.formula(paste("idx~",varname,sep=""))
dcast(mylist[[varname]], myformula, value_var="var1")
}
# loop over list elements, by name
lapply(names(mylist), myfunc)