长格式数据按年统计目标变量为1的占比:NA处理导致结果异常
问题与解决方案
问题背景
我有一个长格式数据框vbid_nodup_merged_filtered,其中变量pbp_b10b_bendesc_lim_al的取值为2(代表No)、1(代表Yes)或NA。需要统计每年中pbp_b10b_bendesc_lim_al == 1的记录占当年总行数的百分比,但当前使用的代码中,mean()函数的na.rm = TRUE会排除NA值,导致部分年份的占比计算错误(比如某年份大部分是NA,剩余记录都是1时,占比会显示为100%,但实际应该是1的数量除以当年总记录数)。
原代码如下:
vbid_nodup_merged_filtered %>% select(Year, VBID, pbp_b10b_bendesc_lim_al) %>% arrange(Year) %>% add_count(Year) %>% group_by(Year) %>% mutate(pbp_b10b_bendesc_lim_al = ifelse(pbp_b10b_bendesc_lim_al == 1, 1, 0)) %>% mutate(percent_yes = 100*mean(pbp_b10b_bendesc_lim_al, na.rm = TRUE)) %>% slice(1)-> vbid_unlimited_percent
修正方案
核心问题是原代码计算占比时,分母排除了NA值,但我们需要分母是当年的总记录数(包含NA)。以下两种方式可解决问题:
方法1:手动统计分子与分母
直接计算每年中符合条件的记录数,除以当年总记录数:
vbid_nodup_merged_filtered %>% select(Year, pbp_b10b_bendesc_lim_al) %>% group_by(Year) %>% summarise( total_records = n(), yes_count = sum(pbp_b10b_bendesc_lim_al == 1, na.rm = TRUE), percent_yes = 100 * yes_count / total_records ) -> vbid_unlimited_percent
方法2:统一转换非Yes值为0
把NA和2都转为0,此时计算均值的分母就是总记录数,无需排除NA:
vbid_nodup_merged_filtered %>% select(Year, VBID, pbp_b10b_bendesc_lim_al) %>% arrange(Year) %>% group_by(Year) %>% mutate( pbp_b10b_bendesc_lim_al = case_when( pbp_b10b_bendesc_lim_al == 1 ~ 1, TRUE ~ 0 ) ) %>% mutate(percent_yes = 100 * mean(pbp_b10b_bendesc_lim_al)) %>% slice(1) -> vbid_unlimited_percent
补充说明
- 方法1逻辑更清晰,直观区分总记录数与符合条件的记录数,减少歧义;
- 方法2通过
case_when统一处理非1的情况,确保计算均值时包含所有记录,结果准确。
内容的提问来源于stack exchange,提问作者Jenn0804
相关产品推荐
相关产品推荐

