data.table 赋值中评估字符串的快捷方式
Shortcut for evaluating strings in data.table assignments
与 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 赋值中构建要计算的字符串是如此常见,我希望尽可能减少输入。
很多时候甚至不需要进入 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
我们可以使用.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]
与 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 赋值中构建要计算的字符串是如此常见,我希望尽可能减少输入。
很多时候甚至不需要进入 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
我们可以使用.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]