我在一个条件中使用%in%
时遇到了一个意外的输出,同时重新编码一个分类变量。
当左边向量的一个元素是NA
时,条件的计算结果是FALSE
,而我期望它是NA
。
期望的行为是用|
==
条件的更详细的语句。dt <- data.frame(colour = c("red", "orange", "blue", NA))
# Expected
dt$is_warm1 <- ifelse(dt$colour == "red" | dt$colour == "orange", TRUE, FALSE)
# Unexpected
dt$is_warm2 <- ifelse(dt$colour %in% c("red", "orange"), TRUE, FALSE)
dt
#> colour is_warm1 is_warm2
#> 1 red TRUE TRUE
#> 2 orange TRUE TRUE
#> 3 blue FALSE FALSE
#> 4 <NA> NA FALSE
这在重新编码分类变量时非常没有帮助,因为它会静默地填充缺失的值。为什么会发生这种情况,是否有任何替代方案不涉及列出所有==
条件?(想象colour
包含30个可能的关卡)。
a %in% b
只是match(a, b, nomatch = 0) > 0
的简写(检查%in%
的源代码以满足您自己的情况)。
您可以通过删除nomatch = 0
参数获得预期的结果:
match(dt$colour, c("red", "orange")) > 0
#> [1] TRUE TRUE NA NA
当然不需要ifelse
%in%
检查NA
是否在列表中。考虑以下两个场景
NA %in% 1:3
# [1] FALSE
NA %in% c(1:3, NA)
# [1] TRUE
这允许你检查NA是否在向量中
如果您想保留NA值,您可以编写自己的替代
`%nain%` <- function(val, list) {
ifelse(is.na(val), NA, val %in% list)
}
然后你可以使用
dt$is_warm3 <- dt$colour %nain% c("red", "orange")
这是帮助文档中的一些信息?%in%
所以你可以在最后一行看到%in%
从不返回NA,所以这就是为什么它返回FALSE
而不是NA
。它正在检查遗漏的值,正如@MrFlick在他的回答中提到的
确切地说,什么匹配什么在某种程度上是一个定义问题。对于所有类型,NA只匹配NA,不匹配其他值。实数和复数值时,NaN值被视为匹配任何其他NaN值,但是不匹配NA,对于复数x,实部和虚部必须匹配两者(除非包含至少一个NA)。
如果任何输入是字节序列,则将字符串作为字节序列进行比较标记为"字节",如果它们在中,则被视为相等不同的编码,但在翻译为UTF-8时是一致的(参见编码)。
, % %从未在如果返回NA使它特别有用条件。