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

Pet*_*Pan 3 r data.table

我想编写一个函数,在其中构建几个新列.我在处理和命名data.table函数内部的列时遇到了一些问题.说我有:

library(data.table)
DT <- as.data.table(iris)
Run Code Online (Sandbox Code Playgroud)

并说我有兴趣以相同的方式为不同的colums创建新的变量(比方说Sepal.Length,Sepal.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])
Run Code Online (Sandbox Code Playgroud)

但是,如果我想为其他变量执行此操作(Sepal.Width并且Petal.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])
}
Run Code Online (Sandbox Code Playgroud)

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

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

(这在Rolands编辑中得到了回答)

说我想拥有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"))
Run Code Online (Sandbox Code Playgroud)

Rol*_*and 6

没有理由分配功能的结果.:=无论如何通过引用分配.如果要复制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)
Run Code Online (Sandbox Code Playgroud)

修改后续问题:

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"))
Run Code Online (Sandbox Code Playgroud)

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

对于不熟悉上述第一个参数的用户gsub(),请参阅?regex帮助.