Hutchins
Hutchins

Reputation: 131

Is there a consistent guidance on passing names into functions? Example with data.table

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

Answers (1)

Abdessabour Mtk
Abdessabour Mtk

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.
  • As for 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 last one works because you're turning the symbol created by substitute into a character.

Note

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

Related Questions