You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高效实现按group统计class1与class2所有组合计数的方法

高效生成分组下分类变量全组合计数的解决方案

问题背景

给定数据集示例:

df <- tibble(group = c(rep(1, 6), rep(2, 6)),
             class1 = c("A", "A", "B", "B", "B", "C", "B", "B", "B", "C", "C", "C"),
             class2 = c("A", "B", "B", "B", "C", "B", "B", "B", "A", "C", "A", "B"))

需求:按group分组,生成class1与class2所有可能组合的计数表格(包含出现次数为0的组合)。

原方案处理千万级数据集时速度极慢(耗时超30分钟):

output <- df %>% table() %>% as.data.table()

期望输出需包含所有组合,示例如下(注:示例中group字段存在笔误,应为rep(1,9), rep(2,9)):

output <- tibble(group = c(rep(1, 9), rep(2, 9)),
                 class1 = c(rep("A", 3), rep("B", 3), rep("C", 3),
                            rep("A", 3), rep("B", 3), rep("C", 3)),
                 class2 = rep(c("A", "B", "C"), 6),
                 N = c(1, 1, 0, 0, 2, 1, 0, 1, 0, 0, 0, 0, 1, 2, 0, 1, 1, 1))

高效解决方案

方案1:使用data.table(推荐,千万级数据最优)

data.table的分组操作和交叉连接性能远优于基础函数,适合大数据集:

library(data.table)

# 转换为data.table格式
setDT(df)

# 获取class1和class2的所有唯一取值
class1_vals <- unique(df$class1)
class2_vals <- unique(df$class2)

# 1. 分组统计已有组合的计数;2. 生成每个group下的全组合;3. 左连接补全计数并填充0
output <- df[, .N, by = .(group, class1, class2)] %>%
  .[CJ(group = unique(group), class1 = class1_vals, class2 = class2_vals, sorted = FALSE),
    on = .(group, class1, class2)] %>%
  .[is.na(N), N := 0] %>%
  .[order(group, class1, class2)]

方案2:使用dplyr + tidyr(tidyverse用户友好)

如果习惯tidyverse语法,可使用count()配合complete()实现,性能优于原方案:

library(dplyr)
library(tidyr)

output <- df %>%
  # 分组统计已有组合的计数
  count(group, class1, class2) %>%
  # 生成所有可能组合,缺失计数填充为0
  complete(group, class1 = unique(class1), class2 = unique(class2), fill = list(N = 0)) %>%
  # 按顺序排序,匹配期望输出格式
  arrange(group, class1, class2)

方案优势说明

  • 原方案的table()会先构建多维列联表,再转换为数据框,中间过程内存占用大、计算冗余;
  • 上述方案直接先分组统计已有组合的计数,再通过交叉连接补全缺失组合,内存占用更低,计算逻辑更高效,处理千万级数据的耗时可压缩至数分钟甚至更短。

内容的提问来源于stack exchange,提问作者Wilson Souza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 19:25:28