如何基于加拿大体重分箱区间,高效统计美国人群对应分组数据
高效实现基于加拿大数据分箱统计美国人群数据的方法
背景与现有代码
我正在用R做数据分析,现有加拿大人群身高体重数据集,用quantcut函数把体重分成100个分箱,计算了每个分箱的最小体重、最大体重、人数和平均身高,代码如下:
library(dplyr) library(gtools) set.seed(123) canada = data.frame(height = rnorm(10000,150,10), weight = rnorm(10000,90, 10)) Part_1 = canada %>% mutate(quants = quantcut(weight, 100), rank = as.numeric(quants)) %>% group_by(quants) %>% mutate(min = min(weight), max = max(weight), count = n(), avg_height = mean(height)) Part_1 = Part_1 %>% distinct(rank, .keep_all = TRUE)
输出的Part_1结构示例:
# A tibble: 100 x 8 # Groups: quants [100] height weight quants rank min max count avg_height <dbl> <dbl> <fct> <dbl> <dbl> <dbl> <int> <dbl> 1 144. 114. (110.2,113.9] 99 110. 114. 100 150. 2 148. 88.3 (88.12,88.38] 44 88.1 88.4 100 149. 3 166. 99.3 (99.1,99.52] 83 99.1 99.5 100 152. 4 151. 84.3 (84.14,84.44] 29 84.1 84.4 100 150.
另有美国人群数据集:
set.seed(124) usa = data.frame(height = rnorm(10000,150,10), weight = rnorm(10000,90, 10))
需求
基于加拿大数据得出的体重分箱区间,统计每个区间内美国人群的数量及平均身高。目前我只能手动逐个分箱处理,比如:
americans_in_canadian_rank99 = usa %>% filter(weight > 110.2 & weight < 113.9) %>% group_by() %>% summarize(count = n(), avg_height = mean(height)) americans_in_canadian_rank44 = usa %>% filter(weight > 88.1 & weight < 88.4) %>% group_by() %>% summarize(count = n(), avg_height = mean(height))
期望输出格式:
# 行数等于唯一分箱数 canadian_rank min_weight max_weight canadian_count canadian_avg_height american_count american_avg_height 1 99 110.2 113.9 100 150 116 150 2 44 88.1 88.4 100 149 154 150
高效解决方案
可以直接利用Part_1中的分箱区间(min和max列),通过cut函数给美国数据的体重分配对应的加拿大分箱rank,再分组统计,最后和加拿大的统计结果合并:
# 提取加拿大分箱的边界,添加极小值避免左边界样本遗漏 breaks = c(min(Part_1$min) - 1e-8, Part_1$max) # 给美国数据分配对应的加拿大分箱rank并统计 usa_stats = usa %>% mutate(rank = cut(weight, breaks = breaks, labels = Part_1$rank, include.lowest = TRUE)) %>% group_by(rank) %>% summarize(american_count = n(), american_avg_height = mean(height, na.rm = TRUE)) %>% mutate(rank = as.numeric(rank)) # 合并两国统计结果,得到目标格式 final_result = Part_1 %>% select(canadian_rank = rank, min_weight = min, max_weight = max, canadian_count = count, canadian_avg_height = avg_height) %>% left_join(usa_stats, by = c("canadian_rank" = "rank")) # 查看结果示例 head(final_result)
关键说明
- 用
cut函数一次性完成美国体重到加拿大分箱的映射,彻底替代手动写过滤条件的重复工作; include.lowest = TRUE确保最小体重的样本被正确归入第一个分箱;- 给breaks开头添加极小值
1e-8,避免第一个分箱左边界的样本被排除; - 通过
left_join自动匹配分箱rank,直接生成符合需求的合并结果。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

