data.table 将生成的多列分配为新的 data.table(或列表)而不重复名称

Ste*_* J. 5 r names data.table

我的问题是关于将多列分配给 data.table 时代码的易错性/可维护性。

我有一个返回 data.table 的函数,如下所示:

f <- function(x)
{
  # perform some complicated operations on x yielding multiple results

  data.table(col1 = my_result_1, col2 = my_result_2)
}
Run Code Online (Sandbox Code Playgroud)

我将此函数应用于另一个 data.table 的行组,结果将添加为新列(或更新列,如果它们已经存在):

dt <- data.table(x = 1 : 4, id = c(1,1,2,2))
#    x id
# 1: 1  1
# 2: 2  1
# 3: 3  2
# 4: 4  2

dt[, c('col1', 'col2') := f(x), by = id]
Run Code Online (Sandbox Code Playgroud)

从技术上讲,这很好用。但是,我想知道是否有一种优雅的方法可以避免在f():= 的 LHS 上再次指定生成的列名。

Uwe*_*Uwe 0

OP 要求一种优雅的方式,以避免在 的 LHS 上再次指定 f() 中生成的列名称:=

下面的方法既不优雅也不高效,但它避免了创建新的列名,并且如果修改函数以返回更多列或更改输出列名,它将起作用,因此,它解决了容易出错/可维护性的问题OP提出的代码。

library(data.table)

f <- function(x) {
  my_result_1 <- x^2/sum(x)
  my_result_2 <- sum(x)/x
  data.table(col1 = my_result_1, col2 = my_result_2)
}

dt <- data.table(x = 1 : 4, id = c(1,1,2,2))
tmp <- dt[,  f(x), by = id]
dt[, names(tmp) := tmp]
dt[]
Run Code Online (Sandbox Code Playgroud)
   x id      col1     col2
1: 1  1 0.3333333 3.000000
2: 2  1 1.3333333 1.500000
3: 3  2 1.2857143 2.333333
4: 4  2 2.2857143 1.750000
Run Code Online (Sandbox Code Playgroud)

现在,让我们重新定义f()

f <- function(x) {
  my_result_1 <- x^2/sum(x)
  my_result_2 <- sum(x)/x
  my_result_3 <- max(x)/x
  data.table(c1 = my_result_1, c2 = my_result_2, c3 = my_result_3)
}

tmp <- dt[,  f(x), by = id]
dt[, names(tmp) := tmp]
dt[]
Run Code Online (Sandbox Code Playgroud)
   x id      col1     col2        c1       c2       c3
1: 1  1 0.3333333 3.000000 0.3333333 3.000000 2.000000
2: 2  1 1.3333333 1.500000 1.3333333 1.500000 1.000000
3: 3  2 1.2857143 2.333333 1.2857143 2.333333 1.333333
4: 4  2 2.2857143 1.750000 2.2857143 1.750000 1.000000
Run Code Online (Sandbox Code Playgroud)

警告

正如弗兰克所指出的f(x),只有当返回与 相同的行数时,这个答案才有效dt