data.table列名等于变量名

时间:2019-09-09 14:29:39

标签: r data.table

该如何处理?

d <- data.table(
  a = c(1, 2, 3)
)
a <- 2
d[a == a]

给予:

   a
1: 1
2: 2
3: 3

预期结果是:

   a
1: 2

2 个答案:

答案 0 :(得分:5)

我也无意中沦为猎物。通常,这与范围界定有关,而不仅仅是data.tabledplyr会做同样的事情)。通过定义一个在父(或全局)环境中掩盖同名变量的变量,您可以在function正文中发现类似的问题。

a <- 1
# a brain-dead example
myfunc <- function() {
  a <- 2
  a - a
}

在该function示例中,“显而易见”的是a到底是哪个模棱两可,但实际上在您的问题中是同一回事。不安全地假设不等式的LHS或RHS总是在数据内部 ,而另一个在外部 always 如果找不到任何内容,则搜索从内部开始,向外部移动。由于LHS和RHS都位于==的两侧,因此LHS和RHS都使用'inside'。

我想知道是否很难说出“如果在LHS上找到它的“内部”,那么不要在RHS上看到它的“内部”” ,但是我认为这没有必要复杂。尤其是因为搜索变量是在R的常规变量搜索中有效完成的,因此不必在包装代码中手动编码。

最佳答案?不要这样解决方法?之一:

# this "should" always work, assuming "where" the external variable is defined
d[a == get("a", envir=parent.frame())]

# this only works if it is truly in the global environment
d[a == get("a", envir=globalenv())]

# and @nicola's suggestion:
d[a == evalq(a, envir=parent.frame())]

答案 1 :(得分:2)

对此问题有两种替代解决方案:..符号前缀和使用setkey()

为了进行测试,使用了更复杂的示例数据集,其中2的值a位于行2中不是

library(data.table)
d <- data.table(rn = 1:4, a = c(1, 4, 3, 2)) # a more subtle test case
a <- 2

d
   rn a
1:  1 1
2:  2 4
3:  3 3
4:  4 2

..符号前缀

根据data.table NEWS on version 1.10.2 (Jan 2017)

  

j是前缀为..的符号时,它将在呼叫中进行查找   范围及其值应作为列名或数字。

不幸的是,当前仅适用于j=参数,而不适用于i=参数。 (根据data.table NEWS on version 1.11.0, May 2018, new features item 18,它可能还会扩展为出现在i=by=中的符号。)

但是,我们可以使用它来创建逻辑值向量或索引向量,以用于后续子集:

library(magrittr)
d[, a == ..a] %>% d[.]
   rn a
1:  4 2

d[, .I[a == ..a]] %>% d[.]
   rn a
1:  4 2

对于子集,magrittr样式 piping 被用作..符号前缀,尚未实现在i=中使用。因此,将d[, a == ..a]直接用作i=参数(即d[i = d[, a == ..a]])将不起作用(返回未分配的d)。

setkey()

对于使用局部变量da过滤setkey()的不太普遍的用例 可以使用:

setkey(d, a)
d[a]
   rn a
1:  4 2

get("a", pos = 1L)

get("a", pos = 1L)]或更短的get("a", 1L)r2evans' answer中已经建议的get("a", envir=parent.frame()的缩写。

get("a", 1L)在某种程度上等效于..a,但由于可以直接在i=中使用而更加健壮:

d[a == get("a", 1L)]
   rn a
1:  4 2