R:如何在函数内创建和寻址 data.table 的列

标签 r data.table

我想编写一个函数,在其中构建多个新列。我在函数内寻址和命名 data.table 的列时遇到了一些问题。假设我有:

library(data.table)
DT <- as.data.table(iris)

并说我有兴趣以相同的方式为不同的列创建新变量(比方说 Sepal.LengthSepal.WidthPetal.Length )。我想要一个函数,它可以在一个新的列中按物种对所有观测值求和,然后取 Petal.Width 的每个观测值与这个总和的比率。如果我指定列的名称,我有一个工作示例:

thisworks <- function(a){
DT[,named_column1:=sum(eval(a),na.rm=T),by=Species]
DT[,named_column2:=named_column1/Petal.Width]
DT
}
DT <- thisworks(DT[,Sepal.Length])

但是,如果我想对其他变量(Sepal.WidthPetal.Length,总共产生 6 个新列)执行此操作,我想以此为基础评估列名。我的无效尝试:

thisdoesntwork <- function(b){
name1 <- paste0("total_",names(b))
#here, I don't know how to get the name of the column
DT[,assign(name1,sum(eval(column_of_interest),na.rm=T)),by=Species]
name2 <- paste0("ratio_",names(b))
DT[,assign(name2,named_column1/Petal.Width)]
DT
}

for (i in c("Sepal.Length", "Sepal.Width", "Petal.Length"){
# I know I know, loops are evil. However, data.table is fast so i dont mind
DT <- thisdoesntwork(DT[,i,with=F])
}

也非常感谢一般提示。构建两个函数是否更明智,例如,每个任务一个?或者我应该将整个函数写在一个大的 data.table 过滤器中吗?我认为这也可行,不是吗?

编辑:第二种情况:分别使用两个不同的列创建两个新变量

(这是在 Rolands Edit 中回答的)

假设我想要 ratio_Length=Sepal.Length/Petal.Lengthratio_Width=Sepal.Width/Petal.Width。为什么这不起作用?:

DT <- as.data.table(iris)

myfun <- function(d,variables){
d[, paste0("ratio_",substr(variables,7,99)) := 
mapply(.SD, function(x) x / mget(paste0("Petal.",substr(variables,7,99))),
.SDcols = variables)]
d[]
}
DT <- myfun(DT,c("Sepal.Length","Sepal.Width"))

最佳答案

函数的结果没有理由赋值。 := 无论如何都是通过引用赋值的。如果您想复制 data.table,您需要在函数的开头进行显式的 copy

您可以使用 .SD.SDcols。查看data.table vignettes了解详情。

thisworks <- function(d, cols){
  d[, paste0(cols, 1) := lapply(.SD, sum, na.rm = TRUE), by=Species, .SDcols = cols]
  d[, paste0(cols, 2) := lapply(.SD, function(x) x / d[["Petal.Width"]]), 
     .SDcols = paste0(cols, 1)]
  d[]
}
library(data.table)
DT <- as.data.table(iris)
thisworks(DT, c("Sepal.Length", "Sepal.Width", "Petal.Length"))
print(DT)

编辑您的后续问题:

myfun <- function(d,variables){
  d[, gsub(".*\\.", "Ratio.", variables) := 
      Map("/", mget(variables), mget(gsub(".*\\.", "Petal.", variables)))] 
#might be more efficient to do 
#Map(function(x, y) get(x)/get(y), variables, gsub(".*\\.", "Petal.", variables))
#do some benchmarks
  d[]
}
myfun(DT,c("Sepal.Length","Sepal.Width"))

我只能重申:调用函数时不要赋值。传递给它的 data.table 通过引用更改。

对于不熟悉上面gsub()第一个参数的用户,请引用?regex寻求帮助。

关于R:如何在函数内创建和寻址 data.table 的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37856622/

相关文章:

r - 我如何融化具有连接列名称的 data.table

python - knitr - 导入 python 模块时出错

r - VAR 中的非连续滞后数(R 包 "vars")

R 正则表达式获得部分匹配

r - 在 lapply 中的 data.table 中使用函数

r - dplyr mutate 和 summary 在数据表中的等价物是什么?

r - 将部分字符串拆分为列表列,然后创建向量列

r - 临时连接周围的r.data.table函数包装器(链中聚合)

r - 计算 x^2*y, 5*x+sin(y) 的雅可比矩阵

r - 用另一个掩码数据框揭示一个数据框的值