在R中使用case_when与rowSums时行统计结果不匹配问题
二进制变量编码与行和统计的NA处理差异
问题场景
构建含随机缺失值的二进制变量数据框:
set.seed(357) # 生成二进制变量 var1 <- sample(c(0, 1, NA), 200, replace = TRUE, prob = c(0.4, 0.4, 0.2)) var2 <- sample(c(0, 1, NA), 200, replace = TRUE, prob = c(0.4, 0.5, 0.1)) var3 <- sample(c(0, 1, NA), 200, replace = TRUE, prob = c(0.4, 0.35, 0.25)) # 创建数据框 df <- data.frame(var1, var2, var3)
需求与疑问:
- 生成
x1:任意变量为1则x1=1,所有变量为0则x1=0,用case_when实现后,table(df$x1)输出0有11个,1有167个。 - 用
rowSums(cbind(var1, var2, var3), na.rm = F)生成x2统计行和,table(df$x2)输出0有11个,1有38个,2有51个,3有13个。但x2中1/2/3的总数(102)与x1中1的数量(167)不匹配;尝试na.rm = TRUE后,连0的数量也不匹配。
核心原因:NA的处理规则差异
1. x1的case_when逻辑
对应需求的case_when实现代码如下:
library(dplyr) df <- df %>% mutate(x1 = case_when( var1 == 1 | var2 == 1 | var3 == 1 ~ 1, var1 == 0 & var2 == 0 & var3 == 0 ~ 0 # 未匹配的情况(存在NA且无1的行)自动设为NA ))
这里的规则是:
- 只要行内至少有一个1,不管有没有NA,都标记为1(比如
NA,0,1或NA,1,0这类行都会归为1)。 - 只有行内所有变量明确为0(无NA),才标记为0。
- 存在NA且没有1的行(比如
0,NA,NA)会被设为NA,不计入table(df$x1)的统计结果。
2. rowSums(na.rm = F)的逻辑
rowSums默认na.rm = FALSE,即行内只要有NA,行和直接返回NA。因此:
x2的1/2/3只统计了完全无NA且行内1的数量为1/2/3的行,也就是无缺失的有效行里有1的情况。- 那些有NA但包含1的行(比如
NA,0,1),行和会是NA,不会被计入table(df$x2)的1/2/3中,这就是x1的1(167)和x2的1+2+3(102)数量差的来源(167-102=65行是有NA但含1的行)。
3. rowSums(na.rm = TRUE)的逻辑
当设置na.rm = TRUE时,rowSums会把NA当作0计算,此时:
- 行和为0的情况包括:全0的行,以及有NA但没有1的行(比如
NA,NA,0),所以table(df$x2)的0数量会比x1的0多,和x1的0定义完全不同。
哪个结果正确?
取决于你的业务需求:
- 如果需要只要有1就标记为1,只有所有变量明确为0才标记为0,那
x1的结果是正确的,完全符合你最初的规则。 - 如果需要统计无缺失行内1的个数,那
rowSums(na.rm = F)的结果是对的,但它不包含有NA但含1的行。 - 如果需要把NA当作0来计算行和,那用
rowSums(na.rm = TRUE),但此时的0和你最初定义的x1的0不是同一个概念。
内容的提问来源于stack exchange,提问作者esteban
相关产品推荐
相关产品推荐

