如何使用dplyr统计两列满足条件的分组计数及占比
R分组条件统计问题解决方案
针对分组统计时丢失零计数分组、分母硬编码的问题,以下是可靠实现方法:
dplyr 最优实现
核心调整是放弃先filter再分组统计的逻辑,改为先分组,再在组内直接统计符合条件的样本数,同时自动获取每组实际样本量作为分母,从根源避免两个问题:
library(dplyr) resulta <- tta %>% group_by(group) %>% summarise( n = sum(v1 <= 6 & v2 <= 6), # 直接统计组内符合条件的行数,无需提前筛选 frac = n / n(), # 用n()获取当前组实际样本量,替代硬编码分母 .groups = "drop" )
运行以上代码会直接得到期望输出,分组3会被保留,n=0、frac=0,且不管每组实际样本量是多少,占比计算都准确。
如果场景中存在原始数据里完全没有样本的理论分组(比如分组范围是1-6,但原始数据里没有分组6的任何记录),可以先把分组列转为因子指定完整水平,再配合.drop = FALSE参数保留空分组:
tta$group <- factor(tta$group, levels = 1:5) # 指定所有需要保留的分组水平 resulta <- tta %>% group_by(group, .drop = FALSE) %>% # 关闭空因子水平自动丢弃 summarise( n = sum(v1 <= 6 & v2 <= 6), frac = n / n(), .groups = "drop" )
Base R 原生实现(无需依赖dplyr)
不用第三方包也可以实现同样逻辑,代码如下:
# 按分组统计总样本量 total_n <- tapply(seq_len(nrow(tta)), tta$group, length) # 按分组统计符合条件的样本量 match_n <- tapply(tta$v1 <= 6 & tta$v2 <=6, tta$group, sum) # 合并为结果数据框 resulta <- data.frame( group = as.integer(names(total_n)), n = as.vector(match_n), frac = as.vector(match_n / total_n) )
核心逻辑说明
- 提前全局
filter会直接删除不符合条件的行,对应没有符合条件样本的分组会被完全剔除;改为分组后用sum(逻辑判断)统计,逻辑值TRUE计数为1、FALSE计数为0,零样本组会自动得到n=0,不会丢失 - 分组后用
n()(dplyr)或分组计数函数(base R)动态获取每组样本量作为分母,完全避免硬编码,适配分组样本量不一致的场景
内容的提问来源于stack exchange,提问作者cwind
相关产品推荐
相关产品推荐

