data.table:使用colnames通过引用进行赋值

时间:2016-11-23 13:50:16

标签: r data.table

我想在data.table中通过引用(:=)使用列名进行赋值。调用的函数是在几列上每行进行一些计算。我使用data.table(v1.9.7)的当前开发版本,这使得参数“with = TRUE”不必要。

具有显式变量名称的运行最小示例是:

DT <- data.table(a = 1:10, b = seq(2, 20, 2), c = seq(5, 50, 5))
DT[, out := sum(a, b), by = 1:nrow(DT)]

但是,如果我有很多列,并且我使用包含(选定)列名的单个变量调用该函数,则代码将失败:

DT  <- data.table(a = 1:10, b = seq(2, 20, 2))
col <- colnames(DT)
DT[, out := sum(col), by = 1:nrow(DT)]

编辑:

David Arenburg的回答DT[, out := Reduce( + , .SD), .SDcols = col]适用于此特定情况。但我真的不明白这种方法如何应用于另一个函数调用。我编写了以下函数进行测试:

myfun <- function(x, y, ...){
   in.tmp1 <- x
   in.tmp2 <- c(y, ...)
   out.tmp <- in.tmp1 + mean(in.tmp2)
   return(out.tmp)
}

同样,明确写下列名称可以使用以下方法:

DT <- data.table(a = 1:10, b = seq(2, 20, 2), c = seq(5, 50, 5))
DT[, out := myfun(a,b,c), by = 1:nrow(DT)]

但我无法为其列名指定的data.table中的大型子集制定更通用的解决方案。

1 个答案:

答案 0 :(得分:0)

请考虑以下事项:

library("data.table")

dt <- data.table(a = 1:5, b = 5:1, c = 1, d = 2, e = 5:1)


myfun <- function(x, y, ...){
  in.tmp1 <- x
  in.tmp2 <- c(y, ...)
  out.tmp <- in.tmp1 + mean(in.tmp2)
  return(out.tmp)
}

my_vars <- c("a", "c", "d")

var_list <- mget(my_vars, envir = as.environment(dt))

names(var_list)[1:2] <- c("x", "y")

dt[, "out" := do.call(myfun, var_list)]

这里我们收集my_varsvar_list中的一组任意列,这是dt中相应列的未复制别名列表。可以使用do.call将列作为R中函数的参数传递,但参数列表中的元素名称(此处为var_list)必须与函数的参数名称匹配( myfun有args“x”,“y”和“...”,但最后一个是任意名称的元素。)

如果您想更多地使用data.table而不使用mget,请尝试

## so myfun finds the correct columns for args "x" and "y"
setnames(dt, c("a", "c"), c("x", "y"))

my_vars <- c("x", "y", "d")
dt[, "out" := do.call(myfun, .SD), .SDcols = my_vars]

编辑2017-02-22:在do.call中也允许使用未命名的列。

dt[, "out" := do.call(myfun, unname(as.list(.SD))), .SDcols = my_vars]