基于R语言按性别分体重区间的多维度数据汇总验证
验证并修正R语言体重区间划分代码
问题背景
现有包含体重、哮喘情况(1=患有哮喘,0=未患哮喘)、性别及id的数据集,生成代码如下:
library(dplyr) library(purrr) library(ggplot2) set.seed(123) my_data1 = data.frame(Weight = rnorm(500,100,100), asthma = sample(c(0,1), prob = c(0.7,0.3), replace=TRUE, size= 500)) my_data2 = data.frame(Weight = rnorm(500, 200, 50), asthma = sample(c(0,1), prob = c(0.3,0.7), replace=TRUE, size= 500)) my_data_a = rbind(my_data1, my_data2) my_data_a$gender = "male" my_data1 = data.frame(Weight = rnorm(500,100,100), asthma = sample(c(0,1), prob = c(0.7,0.3), replace=TRUE, size= 500)) my_data2 = data.frame(Weight = rnorm(500, 200, 50), asthma = sample(c(0,1), prob = c(0.3,0.7), replace=TRUE, size= 500)) my_data_b = rbind(my_data1, my_data2) my_data_b$gender = "female" my_data = rbind(my_data_a, my_data_b) my_data$id = 1:2000
需求为:针对男女两种性别,将人群按体重升序划分为固定宽度30单位的区间(例如男性最小体重至最小体重+30为男性第1区间,以此类推),并统计每个区间的人数、区间内最小体重和最大体重。
用户尝试的代码如下:
Part_1 = my_data %>% group_by(gender) %>% mutate(bins = cut(Weight , breaks = pretty(Weight , n = (max(Weight)-min(Weight))/30), include.lowest = TRUE)) %>% mutate(rank = dense_rank(bins)) %>% mutate(new_bins = paste(rank,"_", gender, sep="")) Part_2 = Part_1 %>% group_by(gender, bins) %>% summarize(min_weight = min(Weight), max_weight = max(Weight), count = n()) Part_3 = merge(x=Part_1,y=Part_2, by.x=c("gender","bins"), by.y=c("gender","bins"))
原代码的问题
原代码的核心问题在于使用pretty()函数生成区间断点:
pretty()的设计目标是生成“美观”的数值断点(比如整十、整百),不会严格遵循从组内最小体重开始、固定宽度30的要求。从用户给出的示例输出可以看到,女性的区间是(-100,-50],宽度为50,明显不符合30的固定宽度需求。- 额外的
merge步骤可以简化,无需拆分再合并,直接在分组流程中完成统计更高效。
修正后的代码
以下代码严格按照需求实现固定宽度区间划分,并简化了流程:
library(dplyr) # 按性别分组,生成固定宽度30的体重区间并统计 final_result <- my_data %>% group_by(gender) %>% mutate( # 获取当前性别体重的最小、最大值 group_min = min(Weight), group_max = max(Weight), # 生成断点序列:从组内最小体重向下取整开始,步长30,直到覆盖最大体重 break_points = list(seq(from = floor(group_min), to = ceiling(group_max) + 30, by = 30)), # 划分区间,include.lowest确保最小值被包含在第一个区间 bins = cut(Weight, breaks = unlist(break_points), include.lowest = TRUE) ) %>% # 按性别和区间分组,统计所需指标 group_by(gender, bins) %>% mutate( min_weight = min(Weight), max_weight = max(Weight), count = n(), # 生成区间的升序排名 rank = dense_rank(bins), new_bins = paste(rank, "_", gender, sep = "") ) %>% # 清理临时变量,整理输出列顺序 ungroup() %>% select(gender, bins, Weight, asthma, id, rank, new_bins, min_weight, max_weight, count)
验证说明
- 区间划分逻辑:每个性别内部的断点从该组体重最小值向下取整开始,每次递增30,确保每个区间的宽度严格为30单位。
- 统计指标:
min_weight和max_weight是对应区间内实际的体重极值,count为区间内的人数,完全匹配需求。 - 流程简化:无需拆分数据再合并,通过一次分组流转完成所有操作,代码更简洁高效。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

