我刚刚发现,如果一个变量是基于多个变量重新编码的,case_when可能不起作用。
可重现数据:
data <- data.frame(f103 = c(2, NA, NA, 1, 2, 2),
f76 = c(2, NA, NA, NA, 3, 3),
f4 = c(1,3,3,1,1,2))
下面的代码对var1和var2产生了相同的结果(这不是我想要的):
reprdata <- reprdata %>%
mutate(var1 = f4) %>%
mutate(var1 = case_when(f103 == 2 ~ 3, TRUE ~ as.numeric(var1))) %>%
mutate(var2 = f4) %>%
mutate(var2 = case_when(f103 == 2 ~ 3, f76 == 1 ~ 1, f76 == 2 ~ 2, f76 == 3 ~ 3, TRUE ~ as.numeric(var2)))
下面的代码会产生正确的结果(即我的问题的解决方案):
reprdata <- reprdata %>%
mutate(var1 = f4) %>%
mutate(var1 = case_when(f103 == 2 ~ 3, TRUE ~ as.numeric(var1))) %>%
mutate(var2 = f4) %>%
mutate(var2 = case_when(f103 == 2 ~ 3, TRUE ~ as.numeric(var2))) %>%
mutate(var2 = case_when(f76 == 1 ~ 1, f76 == 2 ~ 2, f76 == 3 ~ 3, TRUE ~ as.numeric(var2)))
(我知道在我的这段数据中,var1的f103条件是多余的,但我不认为它会导致这个问题。)
我很想知道是否有人能向我的解释为什么会出现这个问题以及将来如何预防它。
2条答案
按热度按时间knpiaxh11#
它与
case_when
如何计算有关:它是自下而上的评估,这与大多数人的直觉(我的经验)相反。f76
胜出(您所期望的!)f103
胜出(出乎意料)一个二个一个一个
rhfm7lfc2#
case_when
表达式本质上是if … else if …
的矢量化形式,它的参数一直计算到找到第一个匹配为止,* 然后停止 *。换句话说,这个子表达式
等效于(同样是的矢量化形式)
要将其矢量化,可以使用
ifelse
(或'dplyr'中的if_else
)重写此表达式,但这会过于冗长,而且我不知道如何以紧凑但可读的方式格式化它(以下代码看起来 * 不错 *,但自动格式化程序会向右扩展平面结构,导致代码极度缩进):因此,dplyr给了我们
case_when
来更好地表达这一点,但逻辑是完全相同的。所以,如果你想让
f76
的值优先于f103
的值,你需要反转你的条件:......当然,通过合并测试
f76
值的所有三个案例,可以缩短时间,如另一个答案所示。