评估data.table赋值中的字符串的快捷方式

时间:2016-04-01 00:23:11

标签: r data.table eval

使用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赋值中构建要编译的字符串是如此常见,以至于我希望尽可能减少键入。

2 个答案:

答案 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]