如何在dplyr中正确结合cut与group_by函数?
问题:group_by结合cut函数分组分箱出现异常类别数量
问题背景
尝试将cut()函数与group_by()结合,按V2和V3分组后对V1进行分箱,但生成的类别多达数十个,而非预期的3个。此前已成功用group_by()+ntile()实现分组分位数划分。
可复现代码
library(dplyr) set.seed(1) df <- tibble( V1 = round(runif(1000,min=1, max=1000)), V2 = round(runif(1000, min=1, max=3)), V3 = round(runif(1000, min=1, max=10))) df$V2 = as.factor(df$V2) df$V3 = as.factor(df$V3) # 全局分箱(正常生成3个类别) df$split= cut(df$V1, quantile(df$V1, c(0, .2, .6, 1)), include.lowest = TRUE) # group_by+ntile正常工作 df=df %>% group_by(V2,V3) %>% mutate(quartile_by_group = ntile(V1,4)) # group_by+cut异常,生成大量类别 df=df %>% group_by(V2, V3) %>% mutate(split_by_group = cut(V1, quantile(V1, c(0, .2, .6, 1)), include.lowest = TRUE)) table(df$split_by_group)
问题原因
每个分组内V1的分位数(quantile()结果)数值不同,cut()会基于这些不同的数值生成不同的区间字符串(比如组1的0.2分位数是180,组2的是220,对应区间分别为[1,180]和[1,220])。这些不同的区间在整个数据集中会被识别为独立类别,最终导致类别数量远超预期。
解决方案
通过统一分箱标签的方式,让每个分组的分箱结果映射为固定的3个类别:
方法1:用case_when自定义分箱逻辑
df <- df %>% group_by(V2, V3) %>% mutate( split_by_group = case_when( V1 <= quantile(V1, 0.2) ~ "0-20%", V1 <= quantile(V1, 0.6) ~ "20-60%", TRUE ~ "60-100%" ) %>% factor(levels = c("0-20%", "20-60%", "60-100%")) # 固定因子顺序 ) %>% ungroup() # 查看结果,只有3个类别 table(df$split_by_group)
方法2:保留区间但统一标签
如果需要保留原始区间信息,同时统一类别标识,可以额外生成标签列:
df <- df %>% group_by(V2, V3) %>% mutate( q_vals = list(quantile(V1, c(0, .2, .6, 1))), # 存储分组分位数 split_by_group = cut(V1, q_vals[[1]], include.lowest = TRUE), split_label = factor(split_by_group, levels = split_by_group, labels = c("低区间", "中区间", "高区间")) ) %>% ungroup() table(df$split_label)
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

