我喜欢能够使用像==
和这样的运算符在R中的矩阵元素上进行运算|
:
(m <- matrix(1:4, nrow=2))
# [,1] [,2]
# [1,] 1 3
# [2,] 2 4
m == 2 | m == 3
# [,1] [,2]
# [1,] FALSE TRUE
# [2,] TRUE FALSE
不幸的是,%in%
它没有同样好的行为,而是返回一个向量而不是一个矩阵:
m %in% c(2, 3)
# [1] FALSE TRUE TRUE FALSE
注意到%in%
定义为function(x, table) match(x, table, nomatch = 0L) > 0L
,我认为我可以重新定义match
以获得所需的行为:
match <- function(x, table, nomatch = NA_integer_, incomparables = NULL) {
m <- base:::match(x, table, nomatch, incomparables)
if (is.matrix(x)) matrix(m, nrow(x))
else m
}
如果我显式调用此方法确实有效,则match
在运行时仍然无法获得所需的结果m %in% c(2, 3)
:
match(m, c(2, 3), nomatch=0L) > 0L
# [,1] [,2]
# [1,] FALSE TRUE
# [2,] TRUE FALSE
m %in% c(2, 3)
# [1] FALSE TRUE TRUE FALSE
为什么现在不%in%
返回矩阵?
感谢@joran向我指出这篇出色的文章,为我澄清了为什么%in%
不使用我新定义的match
函数。这是我对正在发生的事情的理解:
用户定义的match
函数存储在全局环境中,而原始match
函数仍存储在namespace:base
:
environment(match)
# <environment: R_GlobalEnv>
environment(base::match)
# <environment: namespace:base>
现在,考虑当我打电话时会发生什么m %in% c(2, 3)
:
%in%
刚刚定义为的函数function(x, table) match(x, table, nomatch = 0L) > 0L
。match
函数,因此它首先在其本地环境中搜索,该本地环境是在函数调用中创建的。match
在那里没有定义。match
是函数的封闭环境。我们可以弄清楚这是怎么回事:environment(`%in%`)
# <environment: namespace:base>
match
(不是用户定义的版本)是在中定义的namespace:base
,因此这是所调用函数的版本。为了使我的矩阵版本%in%
能够正常工作,最简单的方法是遵循@Molx的建议并重新定义,%in%
以便将其存储在全局环境中(请注意,该函数中还有相同版本namespace:base
):
`%in%` <- function(x, table) match(x, table, nomatch = 0L) > 0L
environment(`%in%`)
# <environment: R_GlobalEnv>
现在,m %in% c(2, 3)
将match
首先在其本地函数环境中搜索该函数,然后在封闭的环境(R_GlobalEnv
)中搜索该函数,以找到我们用户定义的match
函数版本:
m %in% c(2, 3)
# [,1] [,2]
# [1,] FALSE TRUE
# [2,] TRUE FALSE
我们可以%in%
使用用户定义match
函数的另一种方法是将封闭环境更改base::"%in%"
为全局环境:
rm(`%in%`) # Remove user-defined %in%
environment(`%in%`) <- .GlobalEnv # Can be reversed with environment(`%in%`) <- asNamespace("base")
m %in% c(2, 3)
# [,1] [,2]
# [1,] FALSE TRUE
# [2,] TRUE FALSE
正如@Molx答案的评论者所提到的那样,最明智的做法是通过将我的新函数命名为,以避免所有此类头痛%inm%
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句