【问题标题】:Column name equal to variable name [duplicate]列名等于变量名[重复]
【发布时间】:2019-09-09 14:29:39
【问题描述】:

我该如何处理这种情况?

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

给予:

   a
1: 1
2: 2
3: 3

预期结果是:

   a
1: 2

【问题讨论】:

标签: r data.table


【解决方案1】:

我也无意中成为这个的牺牲品。这是关于一般的范围界定,而不仅仅是data.tabledplyr 会做同样的事情)。您可以在 function 正文中找到类似的问题,方法是定义一个变量来掩盖父(或全局)环境中的同名变量。

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

在那个function 示例中,“很明显”a 是哪个完全模棱两可,但在您的问题中实际上是同一回事。假设不等式的 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())]

【讨论】:

  • d[a==evalq(a,envir=parent.frame())] 也可能被添加到列表中。
  • get("a", pos = 1L)]get("a", 1L)get("a", envir=parent.frame()) 的快捷方式。
  • 请注意 get("mean", ...) 返回函数。因此,如果您的列名也与某个函数发生冲突,您必须求助于get("mean", mode = x, ...),而 x 必须匹配 typeof("mean")。另一方面,您可能会被建议避免此类冲突。
【解决方案2】:

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

为了测试,使用了更复杂的样本数据集,其中 a 的值 2 位于第 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 样式 管道 用作 .. 符号前缀尚未实现以在 i= 中使用。因此,直接使用d[, a == ..a] 作为i= 参数,即d[i = d[, a == ..a]] 将不起作用(它返回d unsubsetted)。

setkey()

对于通过局部变量 asetkey() 过滤 d 的不太常见的用例 可以使用:

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

get("a", pos = 1L)

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

get("a", 1L) 在某种程度上等同于..a,但更健壮,因为它可以直接在i= 中使用:

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

【讨论】:

    猜你喜欢
    • 2012-02-21
    • 1970-01-01
    • 2017-10-23
    • 2020-02-01
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    相关资源
    最近更新 更多