R语言:如何自动按等距区间批量分组汇总数值列?
问题描述
现有数据:
(df <- data.frame( random_str = rep("ok", 30), value = rnorm(30, mean=50, sd=25) ))
可通过以下代码按random_str分组计算基本统计量:
df %>% group_by(random_str) %>% summarise(max = max(value), min = min(value) # 其他统计量... )
但还需将value列按指定区间(如0-33、34-66、67-100)分组统计数量,手动实现方式如下:
df %>% group_by(random_str) %>% summarise(max = max(value), min = min(value), # 其他统计量... count1_33 = sum(value < 34), count34_66 = sum(value < 67 & value > 33), count67_100 = sum(value > 66) )
实际场景中有百万行数据,且需设置上百个等距区间,求自动实现这类分组统计的方法。
解决方案
方法1:cut()+count()+pivot_wider()(简洁高效,推荐)
先通过cut()将数值批量分箱,再分组计数后转宽格式,最后和基本统计量合并,完全避免手动编写区间条件:
library(dplyr) library(tidyr) # 定义等距区间:示例为0-100、步长33,上百个区间直接用seq生成即可 breaks <- seq(0, 100, by = 33) # 给区间设置清晰的列名标签 labels <- paste0(breaks[-length(breaks)], "-", breaks[-1]) # 生成区间计数(宽格式) bin_counts <- df %>% mutate(value_bin = cut(value, breaks = breaks, labels = labels, include.lowest = TRUE)) %>% group_by(random_str, value_bin) %>% count(name = "count") %>% pivot_wider(names_from = value_bin, values_from = count, values_fill = 0) # 计算基本统计量 basic_stats <- df %>% group_by(random_str) %>% summarise(max = max(value), min = min(value)) # 合并最终结果 final_result <- basic_stats %>% left_join(bin_counts, by = "random_str")
该方法基于向量化操作,处理百万行数据效率远高于手动写多个sum()条件。
方法2:利用hist()批量生成区间计数
针对严格等距区间,可直接用hist()的统计结果快速生成所有区间计数,无需额外分箱步骤:
library(dplyr) # 定义区间参数 start <- 0 end <- 100 bin_width <- 33 breaks <- seq(start, end, by = bin_width) # 一次性计算基本统计量+所有区间计数 final_result <- df %>% group_by(random_str) %>% summarise( max = max(value), min = min(value), # 用!!!将命名列表展开为列,自动生成区间计数列 !!!set_names( map(value, ~ hist(., breaks = breaks, plot = FALSE)$counts), paste0("count_", breaks[-length(breaks)], "_", breaks[-1]) ) )
方法3:data.table优化大数据性能
如果数据量达到百万级,data.table的分组操作速度和内存效率更突出:
library(data.table) setDT(df) breaks <- seq(0, 100, by = 33) labels <- paste0(breaks[-length(breaks)], "-", breaks[-1]) # 分箱计数并转宽格式 bin_counts_wide <- df[, .(count = .N), by = .(random_str, value_bin = cut(value, breaks = breaks, labels = labels, include.lowest = TRUE))] %>% dcast(random_str ~ value_bin, value.var = "count", fill = 0) # 计算基本统计量 basic_stats <- df[, .(max = max(value), min = min(value)), by = random_str] # 合并结果 final_result <- merge(basic_stats, bin_counts_wide, by = "random_str")
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

