gpt4 book ai didi

R data.table : accessing column with variable name

转载 作者:行者123 更新时间:2023-12-03 23:56:53 25 4
gpt4 key购买 nike

我正在使用美妙的 R data.table 包。但是,使用变量名访问(即通过引用操作)列是非常笨拙的:如果给定一个 data.table dt它有两列 x 和 y,我们要添加两列并将其命名为 z 然后命令是

dt = dt[, z := x + y]

现在让我们写一个函数 add将 a(对 a 的引用)data.table dt 作为参数和三个列名 summand1Name , summand2NameresultName并且应该仅使用通用列名执行与上述完全相同的命令。我现在使用的解决方案是反射,即
add = function(dt, summand1Name, summand2Name, resultName) {
cmd = paste0('dt = dt[, ', resultName, ' := ', summand1Name, ' + ', summand2Name, ']')
eval(parse(text=cmd))
return(dt) # optional since manipulated by reference
}

但是我对这个解决方案绝对不满意。首先,它很笨拙,这样编写代码并不有趣。调试起来很困难,而且只会让我生气并浪费时间。其次,它更难阅读和理解。这是我的问题:

我们可以用更好的方式编写这个函数吗?

我知道这样一个事实,即可以访问具有变量名称的列,如下所示: dt[[resultName]]但是当我写
dt[[resultName]] = dt[[summand1Name]] + dt[[summand2Name]]

然后 data.table 开始提示已经复制而不是通过引用工作。我不想要那个。我也喜欢 dt = dt[<all 'database related operations'>] 的语法这样我所做的一切都被放在一对括号中。是否可以使用反引号等特殊符号来指示当前使用的名称不是引用数据表的实际列,而是实际列名称的占位符?

最佳答案

可以结合使用():= 的 LHS 上以及 with = FALSE在引用 RHS 上的变量时。

dt <- data.table(a = 1:5, b = 10:14)
my_add <- function(dt, summand1Name, summand2Name, resultName) {
dt[, (resultName) := dt[, summand1Name, with = FALSE] +
dt[, summand1Name, with = FALSE]]
}
my_add(dt, 'a', 'b', 'c')
dt

编辑:

比较了三个版本。我的效率最低……(但仅供引用)。
set.seed(1)
dt <- data.table(a = rnorm(10000), b = rnorm(10000))
original_add <- function(dt, summand1Name, summand2Name, resultName) {
cmd = paste0('dt = dt[, ', resultName, ' := ', summand1Name, ' + ', summand2Name, ']')
eval(parse(text=cmd))
return(dt) # optional since manipulated by reference
}
my_add <- function(dt, summand1Name, summand2Name, resultName) {
dt[, (resultName) := dt[, summand1Name, with = FALSE] +
dt[, summand1Name, with = FALSE]]
}
list_access_add <- function(dt, summand1Name, summand2Name, resultName) {
dt[, (resultName) := dt[[summand1Name]] + dt[[summand2Name]]]
}
david_add <- function(dt, summand1Name, summand2Name, resultName) {
dt[, (resultName) := .SD[[summand1Name]] + .SD[[summand2Name]]]
}

microbenchmark::microbenchmark(
original_add(dt, 'a', 'b', 'c'),
my_add(dt, 'a', 'b', 'c'),
list_access_add(dt, 'a', 'b', 'c'),
david_add(dt, 'a', 'b', 'c'))

## Unit: microseconds
## expr min lq mean median uq max
## original_add(dt, "a", "b", "c") 604.397 659.6395 784.2206 713.0315 776.1295 5070.541
## my_add(dt, "a", "b", "c") 1063.984 1168.6140 1460.5329 1247.7990 1486.9730 6134.959
## list_access_add(dt, "a", "b", "c") 272.822 310.9680 422.6424 334.3110 380.6885 3620.463
## david_add(dt, "a", "b", "c") 389.389 431.9080 542.7955 454.5335 493.4895 3696.992
## neval
## 100
## 100
## 100
## 100

编辑2:

有一百万行,结果如下所示。正如预期的那样,原始方法一次性能良好 eval完成后,这将很快奏效。
## Unit: milliseconds
## expr min lq mean median uq max
## original_add(dt, "a", "b", "c") 2.493553 3.499039 6.585651 3.607101 4.390051 114.0612
## my_add(dt, "a", "b", "c") 11.821820 14.512878 28.387841 17.412433 19.642231 117.6359
## list_access_add(dt, "a", "b", "c") 2.161276 3.133110 6.874885 3.218185 3.407776 107.6853
## david_add(dt, "a", "b", "c") 2.237089 3.313133 6.047832 3.381757 3.788558 103.7532
## neval
## 100
## 100
## 100
## 100

关于R data.table : accessing column with variable name,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44152087/

25 4 0