如何在多列中统计特定值的出现次数?(优先dplyr实现)
统计特定值在多列中的出现次数(含缺失值处理)
需求说明
统计特定值在指定多列中的出现次数并存入新列:
- 数据集存在大量缺失值,但仅当整行所有列都是NA时,统计结果才返回NA
- 优先使用dplyr流水线实现
示例数据集
生成含缺失值的示例数据集代码:
df <- data.frame(c1 = sample(1:4, 20, replace = TRUE), c2 = sample(1:4, 20, replace = TRUE), c3 = sample(1:4, 20, replace = TRUE), c4 = sample(1:4, 20, replace = TRUE), c5 = sample(1:4, 20, replace = TRUE)) for (i in 1:5) { df[sample(1:20, 1), sample(1:5, 1)] <- NA df[sample(1:20, 1), ] <- NA }
部分数据集展示:
c1 c2 c3 c4 c5 1 1 2 4 4 1 2 2 2 1 3 4 3 2 4 4 3 3 4 4 2 3 2 1 5 4 2 4 1 3 6 NA 1 2 4 4 7 3 NA 4 NA 4 8 NA NA NA NA NA 9 1 3 3 2 2 10 NA NA NA NA NA
正确实现方法
方法1:dplyr + rowwise + c_across
核心逻辑:先判断整行是否全为NA,是则返回NA;否则用c_across选中目标列,统计特定值出现次数时忽略缺失值。
以统计值2的出现次数为例:
library(dplyr) df <- df %>% rowwise() %>% mutate( count2 = if_all(c1:c5, is.na) ? NA_integer_ : sum(c_across(c1:c5) == 2, na.rm = TRUE) ) %>% ungroup()
统计值4只需修改判断条件:
df <- df %>% rowwise() %>% mutate( count4 = if_all(c1:c5, is.na) ? NA_integer_ : sum(c_across(c1:c5) == 4, na.rm = TRUE) ) %>% ungroup()
方法2:rowSums + case_when(更高效)
针对大数据集,rowwise效率偏低,可改用rowSums结合case_when实现:
df <- df %>% mutate( count2 = case_when( if_all(c1:c5, is.na) ~ NA_integer_, TRUE ~ rowSums(across(c1:c5, ~.x == 2), na.rm = TRUE) ), count4 = case_when( if_all(c1:c5, is.na) ~ NA_integer_, TRUE ~ rowSums(across(c1:c5, ~.x == 4), na.rm = TRUE) ) )
之前尝试的问题分析
- 第一次尝试:未设置
na.rm=TRUE,遇到缺失值时求和结果会变成NA,且未处理整行全NA的场景 - 第二次尝试:
select(where(c1:c5 %in% 2))用法错误,where需接收判断列属性的函数,不能直接判断列值 - rowSums尝试:
select(c1:c5 %in% 4)语法错误,select用于选择列,不能直接做值判断,正确逻辑是用across生成布尔矩阵后再求和
最终结果示例
处理后的数据集部分展示:
c1 c2 c3 c4 c5 count2 count4 1 1 2 4 4 1 1 2 2 2 2 1 3 4 2 1 3 2 4 4 3 3 1 2 4 4 2 3 2 1 2 1 5 4 2 4 1 3 1 2 6 NA 1 2 4 4 1 2 7 3 NA 4 NA 4 0 2 8 NA NA NA NA NA NA NA 9 1 3 3 2 2 2 0 10 NA NA NA NA NA NA NA
内容的提问来源于stack exchange,提问作者BulkySplash
相关产品推荐
相关产品推荐

