Reputation: 131
data(survey)
df <- survey
df$Sex <- as.character(df$Sex)
test <- function(x, y, z){
a <- setDT(x)[, z := .N - 1L, by=y]
setDF(a)
}
test2 <- function(x, y, z){
a <- setDT(x)[, z := .N - 1L, by=substitute(y)]
setDF(a)
}
test3 <- function(x, y, z){
a <- setDT(x)[, z := .N - 1L, by=c(deparse(substitute(y))]
setDF(a)
}
test(df, Sex, dup)
test2(df, Sex, dup)
test3(df, Sex, dup)
Ok, so test and test2 return a "no object" error, but test3 doesn't. I have no idea why. I don't understand why I can't just pass stuff in functions like it would be if I typed it outside a function, and I always end up just trying all the variations until one works. Is there a way to actually know this stuff? Like in this example, why doesn't test and test2 work?
Upvotes: 2
Views: 39
Reputation: 3888
test
is not working because the data.table by
is looking for the object Sex
in the parent frame. the by argument accepts either a list or a vector. this is caused by the lazy evaluation of arguments. y is evaluated to Sex then Sex is not found causing the error to be thrown.test2
it's basically the same issue, if you type typeof(substitute(y))
it'll return "symbol" which is not a list but rather a promise object in R
terms.
A workaround would be to enclose the substitute call in as.character()
.the column created would be named z
as the ?data.table::`:=`
help shows that it's default behavior is to take a symbol. So you'll need to substitute it and deparse it like you did for y.
Upvotes: 1