R语言tidy方案:获取两因子所有组合(含NA/零计数项)计数
统计字段全组合计数(含0计数缺失组合、支持NA值)的tidyverse实现
问题场景
现有示例数据框df结构如下:
df = data.frame( a = c(1978, 1978, 1978, 1978, 1978, 1978, 1979, 1979, 1979, 1980, 1980), b = c("A", "A", "A", "B", "B", "C", "A", "B", "C", "A", "C") )
初始使用group_by()+summarize()计数时,仅返回数据中实际存在的a、b组合,缺失组合(如a=1980, b=B)不会出现,也无法便捷支持NA值的组合统计。
最简实现方案
直接使用tidyr包提供的complete()函数即可,该函数属于tidyverse生态,完全符合tidy风格写法,不需要写循环或冗余判断。
代码示例
library(tidyverse) # 写法1:沿用group_by+summarize逻辑,补全组合 test = df %>% group_by(a, b) %>% summarize(counts = n(), .groups = "drop") %>% # 自动生成a、b所有取值的笛卡尔积,缺失组合的counts填0,保留NA值作为合法分组 complete(a, b, fill = list(counts = 0), na.rm = FALSE) # 写法2:用count()简化分组计数步骤,效果完全一致 test = df %>% count(a, b, name = "counts") %>% complete(a, b, fill = list(counts = 0), na.rm = FALSE)
代码说明
complete()会自动提取传入列(这里是a、b)的所有唯一取值,生成全量组合笛卡尔积,自动匹配原有计数结果,匹配不到的组合按fill参数指定的值填充,设置为0刚好满足0计数需求。- 设置
na.rm = FALSE后,列中存在的NA值会被作为独立的分组取值参与全组合生成,不需要额外写条件判断处理NA。 - 如果你明确知道某一列的固定取值范围(比如b列固定包含A/B/C三类,哪怕某份数据里完全没出现B也要补全),可以在
complete()中手动指定取值列表,例如complete(a = unique(a), b = c("A","B","C"), fill = list(counts=0)),避免遗漏数据中未出现的预期组合。
示例运行结果
针对提供的示例df,运行上述代码后会自动补全缺失的1980-B组合,输出结果如下:
# A tibble: 9 × 3 a b counts <dbl> <chr> <dbl> 1 1978 A 3 2 1978 B 2 3 1978 C 1 4 1979 A 1 5 1979 B 1 6 1979 C 1 7 1980 A 1 8 1980 B 0 9 1980 C 1
注:初始运行得到的结果存在重复行,是因为旧版本dplyr中
summarize()默认不会取消所有分组,在summarize()中添加.groups = "drop"参数,或者直接使用count()函数即可避免这个问题。
内容的提问来源于stack exchange,提问作者colebrookson
相关产品推荐
相关产品推荐

