动态列名似乎在使用 := 时有效,但在 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
使用这个虚拟数据集
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