'How do I correctly use the env variable for data.tables within a function
Let us take a simple example
data <- data.table::data.table(a = 1:10, b = 2:11)
j <- quote(c("c") := list(a + 1))
data[, j, env = list(j = j)][]
# a b c
# <int> <int> <num>
# 1: 1 2 2
# 2: 2 3 3
# 3: 3 4 4
# 4: 4 5 5
# 5: 5 6 6
The above works and produces the correct output. However if I place this inside a function I get a very different output.
data <- data.table::data.table(a = 1:5, b = 2:6)
test <- function(data, ...) {
dots <- eval(substitute(alist(...)))
j <- call(":=", call("c", names(dots)), unname(dots))
print(j)
data[, j, env = list(j = j)][]
}
test(data = data, c = a + 1)
# `:=`(c("c"), list(a + 1))
# a b c
# <int> <int> <list>
# 1: 1 2 <call[3]>
# 2: 2 3 <call[3]>
# 3: 3 4 <call[3]>
# 4: 4 5 <call[3]>
# 5: 5 6 <call[3]>
I assume that the c = a + 1 is just not being evaluated in the correct environment (i.e. the data.table itself).
EDIT: I am using data.table 1.14.3
Solution 1:[1]
The difference between
j_quote <- quote(c("c") := list(a + 1))
and
j_call <- call(":=", call("c", names(dots)), unname(dots))
is very subtle:
j_call
#`:=`(c("c"), list(a + 1))
j_quote
#`:=`(c("c"), list(a + 1))
all.equal(j_call,j_quote)
[1] TRUE
identical(j_call,j_quote)
[1] FALSE
This difference lies in the list structure:
# j_quote
as.list(j_quote)
[[1]]
`:=`
[[2]]
c("c")
[[3]]
list(a + 1)
# j_call
as.list(j_call)
[[1]]
`:=`
[[2]]
c("c")
[[3]]
[[3]][[1]]
a + 1
Try:
library(data.table)
data <- data.table::data.table(a = 1:5, b = 2:6)
test <- function(data, ...) {
dots <- eval(substitute(alist(...)))
j_call <- call(":=", call("c", names(dots)), call("list",unname(dots)[[1]]))
j_quote <- quote(c("c") := list(a + 1))
cat("j_quote",deparse(j_quote),"\n")
cat("j_call ",deparse(j_call),"\n")
cat("identical:",identical(j_quote,j_call),"\n")
data[, j, env = list(j = j_call)][]
}
test(data = data, c = a + 1)
#> j_quote `:=`(c("c"), list(a + 1))
#> j_call `:=`(c("c"), list(a + 1))
#> identical: TRUE
#> a b c
#> <int> <int> <num>
#> 1: 1 2 2
#> 2: 2 3 3
#> 3: 3 4 4
#> 4: 4 5 5
#> 5: 5 6 6
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
