我正在使用data.table
中的R
(OS X 10.11.6上的版本3.3.2),并注意到从版本1.9.6到1.10.0的行为发生了变化使用:=
运算符和名称的字符串。
我根据索引号重命名循环内的列。以前,我一直在eval(as.symbol("string"))
的两边使用:=
,但这不再适用(这是基于之前question的答案)。通过反复试验,我发现我需要在左侧使用("string")
,在右侧使用eval(as.symbol("string"))
。
以下是演示此行为的MCVE
library(data.table)
dt <- data.table(col1 = 1:10, col2 = 11:20)
## the next lines would be inside a loop that is excluded to simplify this MCVE
colA = paste0("col", 1)
colB = paste0("col", 2)
colC = paste0("col", 3)
## Old code that worked with 1.9.6, but not longer works
dt[ , eval(as.symbol(colC)) := eval(as.symbol(colA)) + eval(as.symbol(colB))]
## New code that now works 1.10.0
dt[ , (colC) := eval(as.symbol(colA)) + eval(as.symbol(colB))]
我查看了data.table
documentation并且无法弄清楚为什么这项工作有效。所以,这是我的问题:
为什么我需要右侧的eval(as.symbol("string"))
,而不是左侧?
答案 0 :(得分:3)
从discussion开始,现在假设如果j
是单个字符串,则将其评估为符号,例如,dt[, "col" := 3]
也可以。
当这成为默认设置时,确实有一些变化,但完整的故事包含在上一篇文章和data.table
news中。
然而,您可能会感兴趣
new_cols = c("j1", "j2")
dt[, (new_cols) := value] # brackets so we don't just make a new_col col
或
dt[, c("j1", "j2") := value]
您可以在不需要循环的情况下实现上述目标
library(data.table)
dt = data.table(a = c(2, 3), b = c(5, 7), c = c(11, 13))
cols1 = sapply(c("a", "b"), as.symbol)
cols2 = sapply(c("b", "c"), as.symbol)
new_cols = c("d", "e")
> print(dt)
a b c
1: 2 5 11
2: 3 7 13
dt[, (new_cols) := purrr::map2(cols1, cols2, ~ eval(.x) + eval(.y))]
a b c d e
1: 2 5 11 7 16
2: 3 7 13 10 20