【问题标题】:Assigning/Referencing a column name in data.table dynamically (in i, j and by)动态分配/引用 data.table 中的列名(在 i、j 和 by 中)
【发布时间】:2020-03-23 16:53:57
【问题描述】:

A) 而不是这个(cars <- data.table(cars))

cars[ , .(`Totals:`=.N), by=speed]  

我需要这个

strColumnName <- "Totals:"
cars [ , strColumnName = .N, by=speed]  

怎么做?

B) 类似(更一般的情况)- 而不是这样:

cars[ dist > 50, .(`Totals:`=.N, x=dist*100), by=speed] 

我需要这个:

strFactor <- "dist"
cars[ strFactor > 50, .(`Totals:`=.N, x=strFactor*100), by=speed] 

这个问题是关于在 data.table 中分配/引用列名变量的一般方式,即在“j”(RHS 和 LHS)以及“i”和“by”中 - 动态。当在代码的其他地方选择时需要这样做(例如,用户可以在闪亮的应用程序中输入它们)

C) 涉及 i,j 和 by 的一般情况 - 而不是这个:

 cars[ dist > 50, .(`Totals x Factor: ` = .N * dist), by=speed] 

我需要这个:

strFactor <- "dist"; 
strNewVariable <- "Totals x Factor: "
strBy <- "speed"
cars[ strFactor > 50, .(strNewVariable = .N * strFactor), by=strBy] 

【问题讨论】:

  • 以下不起作用col &lt;- strColumnName ; cars[ , (col) = .N, by=speed] ; cars[ , .((col) = .N), by=speed] ; cars[ , .((col) = .N), by=speed, with=F] ; cars[ , .(as.name(col) = .N), by=speed, with=F]
  • cars[ , .N, by=speed] 是一个聚合,而不是一个赋值。请澄清你到底想要达到什么目的。对于分配,有许多具有相似头衔的骗子,例如stackoverflow.com/questions/11745169/…
  • 您需要使用 := 设置符号。
  • 在我的示例中,可以使用任何其他 RHS 语句代替 .N。这与:= 无关

标签: r data.table


【解决方案1】:

编辑: 根据您的说明,这是setNames 和get 的一种方法。这里的技巧是.. 指示在调用环境中进行评估。

library(data.table)
cars <- data.table(cars)
strFactor <- "dist"
strNewVariable <- "Totals x Factor: "
strBy <- "speed"
cars[ get(strFactor)  > 50, 
     setNames(.(.N * get(..strFactor)),strNewVariable),
     by=strBy] 

【讨论】:

  • 是的 - 我一直认为它必须以某种方式使用get() 完成!整洁的! - 我要编辑我的问题 - 因为在我的编码实践中,我正在尝试“自动化”(即动态分配所有变量)data.table 内的所有部分,即 i、j 和 by
  • 太棒了! - 这就是我从现在开始使用的,唯一的变化是我将使用eval(as.name(strFactor)) 而不是get(..strFactor) - 正如@akrun 所建议的那样,因此无需记住新的.. 符号,什么时候我们可以没有它。伊恩,也许,您可以将这种可能的修改添加到您的答案中,我会接受它作为最佳答案。
  • +1。 by 参数不需要eval - 这将工作by = strBy。此外,对于喜欢避免使用get 的人,您可以分别将cars[[strFactor]] &gt; 50 和.SD[[strFactor]] 用于i 和j 语句。更强大的 API 也在开发中:github.com/Rdatatable/data.table/pull/4304
【解决方案2】:

我们可以使用:= 并用() 包装变量来评估它,而不是逐字逐句地赋值

library(data.table)
cars[ , (strColumnName) := .N, by=speed]  

如果我们需要一个汇总列,

setnames(cars[, .N, by = speed], 'N',  strColumnName)[]

使用更新的代码

cars[eval(as.name(strFactor)) > 50, .(`Totals:`=.N, x=eval(as.name(strFactor))*100), by=speed]

【讨论】:

  • 所以eval(as.name(strFactor)) 与get(strFactor) 相同。凉爽的!从未知道。谢谢!
  • @IVIM 是的,与get相比,ii 更安全
猜你喜欢
  • 1970-01-01
  • 2020-04-13
  • 2012-03-31
  • 2014-06-21
  • 2017-10-06
  • 2013-02-02
  • 2012-07-29
  • 1970-01-01
  • 2018-11-21
相关资源
最近更新 更多