【问题标题】:R eval(as.name(paste0())) wrapper function for programmatic data.table changingR eval(as.name(paste0())) 用于编程 data.table 更改的包装函数
【发布时间】:2021-05-06 01:06:24
【问题描述】:

我想在 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)

【问题讨论】:

  • 就像一个注释,您可能想查看这个待定 PR,它将介绍一种更通用的 data.table 查询编程方式github.com/Rdatatable/data.table/pull/4304
  • 所以这些新功能将在下一版 data.table 中发布?
  • 顺便说一句,这会很棒。对你的工作感到惊讶..
  • 让我们保守地说“即将出版的版本”????

标签: r function data.table eval


【解决方案1】:

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

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

【讨论】:

  • 这太棒了!没想到用lapply。你知道为什么 sa
  • 不是临时的,抱歉。我对元编程的使用不足以让我直观(并且像这样在元编程之外工作是相当直截了当的,所以我坚持使用它)。
  • 是的,如果您要操作整个 data.table,我认为 lapply 往往是一个很好的解决方案,但我觉得在操作数据切片时它会变得混乱(至少对我而言)。表...
  • 我不反对。我防止这种情况的方法是使用.SDcols 并将其捕获到名称向量中((nmsout))。例如,DT[, c("aa","bb") := .(1, 2)] 做了人们可能期望的事情(至少 I 做了什么 :-),我倾向于坚持这种命名法和结构。一旦你发现.( ... ) 只是list(...),那么lapply 似乎更有意义,因为它总是返回一个list
猜你喜欢
  • 2021-10-30
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 2013-03-02
  • 1970-01-01
  • 2018-09-25
相关资源
最近更新 更多