R data.table:如何使用包含列名的 R 变量?

Posted

技术标签:

【中文标题】R data.table:如何使用包含列名的 R 变量?【英文标题】:R data.table: how to use R variables that contain column names? 【发布时间】:2022-01-15 21:32:58 【问题描述】:

我已经读过data.table documentation 好几遍了,但我仍然无法理解如何进行一些操作;更一般地说,我仍然不了解如何使用变量名的潜在“哲学”。考虑这个示例问题:

我有一个包含变量“a”、“b”、“c”、“d”的数据表:

> dt <- data.table(a=c(1,1,2), b=1:3, c=11:13, d=21:23)
> dt
   a b  c  d
1: 1 1 11 21
2: 1 2 12 22
3: 2 3 13 23

假设我的脚本以交互方式要求用户输入用于选择行的列名和相应的值。这两个变量分别存放在rowselectnamerowselectvalue中:

> rowselectname
[1] "a"
> rowselectvalue
[1] 1

该脚本还以交互方式要求用户选择一些感兴趣的行名;他们的名字存储在colselectnames:

> colselectnames
[1] "b" "d"

现在我想从dt 创建一个新的数据表,其中rowselectname 具有rowselectvalue 值的行和colselectnames 给出的列。我最终设法做到这一点的唯一方法如下:

> newdt <- dt[get(rowselectname)==rowselectvalue, ..colselectnames]
> newdt
   b  d
1: 1 21
2: 2 22

我不明白为什么我必须使用get() 作为第一个选择,而.. 作为第二个选择。为什么两者都不是get()(它不起作用)?或者为什么两者都不是..(也不起作用)?这对我来说似乎不一致,但也许有另一种方法可以使用更一致的语法来做到这一点。我认为最明显的应该是 newdt &lt;- dt[rowselectname==rowselectvalue, colselectnames],这就是 R 的其余部分似乎是如何工作的。

非常感谢有人向我解释如何看待这个以理解语法。

【问题讨论】:

这方面正在做的一些工作github.com/Rdatatable/data.table/issues?q=label%3Aprogramming+ 【参考方案1】:

我们可以在.SDcols 中指定colselectnames 并选择.SD - 因为我们将列名作为字符串提供,get 用于返回列的值。也可以通过转换为符号并求值来完成(eval(as.name(rowselectname)))

dt[get(rowselectname)==rowselectvalue, .SD, .SDcols =  colselectnames]
   b  d
1: 1 21
2: 2 22

如果我们想使用.. 运算符,请在j 中使用它

dt[dt[, ..rowselectname][[1]] == rowselectvalue, ..colselectnames]
   b  d
1: 1 21
2: 2 22

【讨论】:

感谢您的建议,但这里的语法也不明显。仍然想知道为什么我必须使用get() 进行第一次选择,而使用非常复杂的语法使用.SD 进行第二次选择。 @pglpm 如果是单列,也可以使用[[提取列值。 .. 是一个特殊的运算符。dt[dt[[rowselectname]]==rowselectvalue, .SD, .SDcols = colselectnames] 谢谢,是的,我知道(就像数据框一样)。不幸的是,在这种情况下,必须选择多个列。 @pglpm 有些运算符在i 中不起作用。在这里,如果您在j 中执行此操作,即dt[dt[, ..rowselectname][[1]] == rowselectvalue, ..colselectnames] b d 1: 1 21 2: 2 22 这个我不知道,谢谢你的例子。【参考方案2】:

随着即将推出的data.table version 1.14.3,get 将被淘汰,您将能够使用新的 env 参数:

添加了用于对 data.table 进行编程的新接口,关闭了 #2655 和许多其他相关问题。它是通过 [.data.table 的新 env 参数使用基本 R 的类替代接口构建的。有关详细信息,请参阅新的小插图 programming on data.table 和新的 ?substitute2 手册页。

# install dev version
install.packages("https://github.com/Rdatatable/data.table/archive/master.tar.gz",  repo = NULL, type = "source")

library(data.table)

dt[rowselectname==rowselectvalue, ..colselectnames, env=list(rowselectname=rowselectname)]

   b  d
1: 1 21
2: 2 22

【讨论】:

太棒了!它使数据表语法更接近标准 R 语法,非常有用。【参考方案3】:

data.table 允许使用on 参数和辅助索引进行快速子集(参见小插图Secondary indices and auto indexing,特别是第2 章)。

使用on 参数我们可以写

library(data.table)
dt[.(rowselectvalue), on = rowselectname, ..colselectnames]
       b     d
   <int> <int>
1:     1    21
2:     2    22

这个简洁的代码类似于 data.table join,其中第二个 data.table 是即时创建的。


如果在rowselectname 列中找不到rowselectvalue,则可以通过nomatch 参数控制结果。

默认返回NA列,例如,

dt[.(rowselectvalue + 10), on = rowselectname, ..colselectnames]
       b     d
   <int> <int>
1:    NA    NA

参数nomatch = NULL确保返回一个空的data.table,例如,

dt[.(rowselectvalue + 10), on = rowselectname, ..colselectnames, nomatch = NULL]
Empty data.table (0 rows and 2 cols): b,d

【讨论】:

感谢您提供此信息。我的困惑仍然存在,语法仍然违反直觉和不规则。看起来我们需要将.() 用于一件事,将.. 用于另一件事;与get().. 没有太大区别。

以上是关于R data.table:如何使用包含列名的 R 变量?的主要内容,如果未能解决你的问题,请参考以下文章

使用 data.table 时如何从字符向量创建列名

R之data.table 介绍

如何在 R 中迭代地过滤列表中的列表或如何同时使用两个条件过滤 data.table,在运行时创建对象

如何使用 R 交换 data.table 中的列值

是否可以使用R data.table函数foverlaps来查找两个表中重叠范围的交集?

R在for循环中从data.table中提取元素[重复]