使用data.table
对数据进行争吵,我发现自己写了很多这样的第三行:
DT = data.table(a = 1:10)
name = 'a'
DT[,eval(parse(text=sprintf('%s_plus_one := %s + 1',name,name)))]
我希望减少到
DT[,s('%s_plus_one := %s + 1',name,name)]
使用如下函数:
# s is *very* short for substitute and evalute
s <- function(...)
eval(parse(text=sprintf(...)))
然后我收到了这个错误:
> DT[,s('%s_plus_one := %s + 1',name,name)]
Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").
我知道我可以这样做:
# sp is short for substitute and parse
sp <- function(...)
parse(text=sprintf(...))
DT[,eval(sp('%s_plus_one := %s + 1',name,name))]
DT
#> a a_plus_one
#> 1: 1 2
#> 2: 2 3
#> 3: 3 4
#> 4: 4 5
但是在data.table赋值中构建要编译的字符串是如此常见,以至于我希望尽可能减少键入。
答案 0 :(得分:7)
很多时候甚至不需要进入eval(parse())
的世界。即,对于此示例,将名称放在左侧的括号中,并在右侧使用get
:
DT[, (paste0(name,"_plus_one")) := get(name) + 1]
DT
# a a_plus_one
# 1: 1 2
# 2: 2 3
# 3: 3 4
# 4: 4 5
# 5: 5 6
# 6: 6 7
# 7: 7 8
# 8: 8 9
# 9: 9 10
#10: 10 11
答案 1 :(得分:2)
我们可以使用.SDcols
DT[,(paste0(name,"_plus_one")) := .SD+1, .SDcols=name]
DT
# a a_plus_one
# 1: 1 2
# 2: 2 3
# 3: 3 4
# 4: 4 5
# 5: 5 6
# 6: 6 7
# 7: 7 8
# 8: 8 9
# 9: 9 10
#10: 10 11
正如@thelatemail所提到的,这也适用于多列
DT = data.table(a = 1:10, b=2:11)
name <- c("a","b")
DT[,(paste0(name,"_plus_one")) := .SD + 1, .SDcols=name]