R eval(as.name(paste0())) 用于程序化 data.table 更改的包装函数

R eval(as.name(paste0())) wrapper function for programmatic data.table changing

我想在 R 中模仿 STATA 的本地宏。 基本上,假设我有一个 data.table,它有许多具有相同起始字符串但不同结束字符串的变量;我想以编程方式更改它。我知道您可以使用 eval(as.name(x)) 来执行此操作,但是在我的代码中执行这么多次会很忙。 有人对此有解决方案吗?

例如

library(data.table)    
a <- data.table(bob_1 = c(1:3), bob_2 = c(1:3), bob_3 = c(1:3))


# this works
for (i in c(1:3)){
  a[,(paste0("bob_",i)):=eval(as.name(paste0("bob_",i))) + 1]
}
a <- as.data.table(a)
print(a)

# this also works
a <- data.table(bob_1 = c(1:3), bob_2 = c(1:3), bob_3 = c(1:3))

for (i in c(1:3)){
  a[,(paste0("bob_",i)):=.SD + 1, .SDcols = (paste0("bob_",i))]
}

a <- as.data.table(a)
print(a)

# but this doesn't

sa <- function(...) {eval(as.name(paste0(...)))}

a <- data.table(bob_1 = c(1:3), bob_2 = c(1:3), bob_3 = c(1:3))

for (i in c(1:3)){
  a[,(paste0("bob_",i)):=sa("bob_",i) + 1]
}
# <<error message>>
a <- as.data.table(a)
print(a)

你很接近。我认为一个简单的方法是这样的:

nms <- grep("^bob_", colnames(a), value = TRUE)
nms
# [1] "bob_1" "bob_2" "bob_3"

a[, (nms) := lapply(.SD, `+`, 1), .SDcols = nms ]
a
#    bob_1 bob_2 bob_3
#    <num> <num> <num>
# 1:     2     2     2
# 2:     3     3     3
# 3:     4     4     4

如何生成我在这里制作的nms向量是任意的。其实不需要两边都一样:

a <- data.table(bob_1 = c(1:3), bob_2 = c(1:3), bob_3 = c(1:3))
nms
# [1] "bob_1" "bob_2" "bob_3"
nmsout <- paste0(nms, "_out")
a[, (nmsout) := lapply(.SD, `+`, 1), .SDcols = nms ]
a
#    bob_1 bob_2 bob_3 bob_1_out bob_2_out bob_3_out
#    <int> <int> <int>     <num>     <num>     <num>
# 1:     1     1     1         2         2         2
# 2:     2     2     2         3         3         3
# 3:     3     3     3         4         4         4