【问题标题】:Combining multiple lists of variable names in data.table?在data.table中组合多个变量名列表?
【发布时间】:2015-07-15 17:17:49
【问题描述】:

我正在尝试将两个单独的变量名列表传递到 data.table (v1.9.4) 中。它返回正确的列,但会删除变量名。这按预期工作:

dt <- data.table(a=1:3, b=4:6, c=7:9, d=10:12)
dt
   a b c  d
1: 1 4 7 10
2: 2 5 8 11
3: 3 6 9 12

传递单个名称列表也可以正常工作:

dt[,list(a,b)]
   a b
1: 1 4
2: 2 5
3: 3 6

但是当我需要传递多个列表时,它会返回正确的列但会去掉变量名:

dt[,c(list(a,b), list(c,d))]
   V1 V2 V3 V4
1:  1  4  7 10
2:  2  5  8 11
3:  3  6  9 12

为什么是两个列表?我正在使用多个引用()的变量列表。我已阅读 FAQ 问题 1.6,并且我知道一种解决方法是使用 with=FALSE 的字符向量。但我的真实用例涉及将名称和表达式的混合传递给函数,例如,

varnames <- quote(list(a,b))
expr <- quote(list(a*b, c+d))
function(dt, varnames, expr) {
  dt[,c(varnames, expr)]
}

我希望“varnames”列有它们的专有名称(如果你只传递一个类似的列表,它们就会这样做

dt[,list(a,b,a*b,c+d)]
   a b V3 V4
1: 1 4  4 17
2: 2 5 10 19
3: 3 6 18 21

如何在 data.table 中组合多个列表,使其仍返回正确的列名? (我不完全确定这是否是 data.table 问题,或者我只是在尝试在 R 中组合列表的方式中做一些愚蠢的事情,但 c() 似乎做了我想做的事。)

【问题讨论】:

  • 它适用于命名列表,但不确定这是否适合您的目的。 dt[,c(list(a = a, b = b), list(c = c,d = d))]
  • 有趣——谢谢!这当然是一种解决方法,它比常见问题解答 1.6 的解决方法更好,因为它也适用于表达式(不仅仅是变量名)。但我仍然想知道是否有一种方法可以组合未命名列表,以便它与常规(干净!)data.table 语法一起使用。 (或者,如果我在组合引用列表的方式上做了一些愚蠢的事情。)
  • @cauchy 你没有做错任何事,data.table 只是通过将未命名列表转换为命名列表来帮助你在简单列表的情况下,但它不能这样做更复杂的情况,因为意图不明确

标签: r data.table


【解决方案1】:

另一种选择是提前构建完整的调用:

varnames[4:5] <- expr[2:3]  # this results in `list(a, b, a * b, c + d)`
dt[, eval(varnames)]

产生:

   a b V3 V4
1: 1 4  4 17
2: 2 5 10 19
3: 3 6 18 21

更一般地说,假设您有一个引用的表达式列表:

exprlist <- list(quote(list(a, b)), quote(list(c, c %% a)), quote(list(a + b)))
expr <-  as.call(Reduce(function(x, y) c(as.list(x), as.list(y)[-1]), exprlist))  # @eddi
dt[, eval(expr)]

【讨论】:

  • 酷!我没有意识到可以做到这一点。此外,从未见过这种分配有效的情况,但c(varnames,expr[-1]) 没有。 exprs 很奇怪。
  • 很酷 - 我建议简化为:as.call(Reduce(function(x, y) c(as.list(x), as.list(y)[-1]), exprlist))
  • @eddi,太好了,我正在尝试做一些类似的事情,但无法让它发挥作用。
  • @Frank,是的,那是因为没有c 方法可以用于执行@eddi 建议的调用。但是请注意,您实际上可以c 两个expressionsexpression() 生成。
  • 谢谢!我从这个中学到了很多!我仍然希望有一种更清洁的方法来做到这一点,但这让我可以编写一个简单的辅助函数,它可以组合列表并且不会严重污染 data.table[ 调用。
【解决方案2】:

这是使用.SD的可能解决方法

varnames <- quote(list(a,b))
expr <- quote(list(a*b, c+d))

myFunc <- function(dt, varnames, expr) {
  dt[, c(.SD[, eval(varnames)], eval(expr))]
}

myFunc(dt, varnames, expr)

#    a b V1 V2
# 1: 1 4  4 17
# 2: 2 5 10 19
# 3: 3 6 18 21

【讨论】:

  • 哇,我很惊讶它在这种情况下有效。我猜 .SD() 返回附有名称的列,因此它的工作原理与上面 docendo discimus 建议的命名列表相同。对我来说,这样做的主要缺点是我有数万列并且只需要少量变量,并且当您不使用大部分列时,.SD() 确实效率低下。
猜你喜欢
  • 2020-08-25
  • 1970-01-01
  • 2018-05-10
  • 1970-01-01
  • 1970-01-01
  • 2012-07-26
  • 2020-12-15
  • 2021-02-23
  • 2022-11-15
相关资源
最近更新 更多