动态列名似乎在使用 := 时有效,但在 data.table 中使用 = 时无效

dynamic column names seem to work when := is used but not when = is used in data.table

使用这个虚拟数据集

setDT(mtcars_copy<-copy(mtcars))
new_col<- "sum_carb" # for dynamic column referencing

为什么案例 1 有效而案例 2 无效?

# Case 1 - Works fine
mtcars_copy[,eval(new_col):=sum(carb)] # Works fine


# Case 2:Doesnt work
aggregate_mtcars<-mtcars_copy[,(eval(new_col)=sum(carb))] # error
aggregate_mtcars<-mtcars_copy[,eval(new_col)=sum(carb))] # error
aggregate_mtcars<-mtcars_copy[,c(eval(new_col)=sum(carb))] # Error

如何让 Case 2 工作,我不希望主 table(mtcars_copy 在这种情况下保存新列)但要将结果存储在单独的聚合 table (aggregate_mtcars)

我想你想要的是在做案例1时简单地复制一份。

aggregate_mtcars <- copy(mtcars_copy)[, eval(new_col) := sum(carb)]

保留 mtcars_copy 作为新 aggregate_metcars 的单独数据集,没有新列。

一种选择是使用基本 R 函数setNames

aggregate_mtcars <- mtcars_copy[, setNames(.(sum(carb)), new_col)]

或者您可以使用 data.table::setnames

aggregate_mtcars <- setnames(mtcars_copy[, .(sum(carb))], new_col)

原因是因为案例 2 使用 data.frame 方式在数据框中创建列(作为新列表)。 data.table 中有隐藏参数:with 处理返回对象的方式。它可以是 data.table 或向量。

?data.table :
By default with=TRUE and j is evaluated within the frame of x; column names can be used as variables. In case of overlapping variables names inside dataset and in parent scope you can use double dot prefix ..cols to explicitly refer to 'cols variable parent scope and not from your dataset.

When j is a character vector of column names, a numeric vector of column positions to select or of the form startcol:endcol, and the value returned is always a data.table. with=FALSE is not necessary anymore to select columns dynamically. Note that x[, cols] is equivalent to x[, ..cols] and to x[, cols, with=FALSE] and to x[, .SD, .SDcols=cols].

# Case 2 :
aggregate_mtcars<-mtcars_copy[,(get(new_col)=sum(carb))] # error
aggregate_mtcars<-mtcars_copy[,eval(new_col)=sum(carb))] # error
aggregate_mtcars<-mtcars_copy[,c(eval(new_col)=sum(carb))] # Error

mtcars_copy[, new_col, with = FALSE ] # gives a data.table
mtcars_copy[, eval(new_col), with = FALSE ] # this works and create a data.table
mtcars_copy[, eval(new_col), with = TRUE ] # the default that is used here with error
mtcars_copy[, get(new_col), with = TRUE ] # works and gives a vector

# Case 2 solution : affecting values the data.frame way
mtcars_copy[, eval(new_col) ] <- sum(mtcars_copy$carb) # or any vector
mtcars_copy[[eval(new_col)]] <- sum(mtcars_copy$carb) # or any vector