如何用tidy方式结合summarise函数计算两类分组相关中位数
问题描述
现有数据集如下:
| id | type | value |
|---|---|---|
| x1 | A | 1 |
| x1 | A | 2 |
| x1 | A | 3 |
| x1 | B | 2 |
| x1 | B | 4 |
| x1 | B | 6 |
| x1 | C | 1 |
| x1 | C | 3 |
| x1 | C | 5 |
需要生成两类汇总列:
- 每个
type分组对应的value的中位数; - 排除当前
type后,其余所有type的value的中位数(例如type-A对应type-B和C的value中位数)
期望输出结果:
| id | type | median_type_value | median_non_type_value |
|---|---|---|---|
| x1 | A | 2 | 3.5 |
| x1 | B | 4 | 2.5 |
| x1 | C | 3 | 2.5 |
目前已实现第一类汇总的代码,但无法完成第二类汇总:
library(tidyverse) df = data.frame(id=c(rep("x1",9)), type=c(rep("A",3),rep("B",3),rep("C",3)), value=c(1,2,3,2,4,6,1,3,5)) df %>% group_by(id,type) %>% summarise(median_type_value=median(value))
解决方案
可以通过先按id分组保存全量数据,再针对每个type筛选排除自身的数据集计算中位数,具体代码如下:
library(tidyverse) df = data.frame(id=c(rep("x1",9)), type=c(rep("A",3),rep("B",3),rep("C",3)), value=c(1,2,3,2,4,6,1,3,5)) df %>% # 按id分组,将当前id下的所有type和value打包为列表列 group_by(id) %>% mutate(all_data = list(tibble(type, value))) %>% # 在id分组基础上新增type分组 group_by(id, type, .add = TRUE) %>% summarise( # 计算当前type分组内的中位数 median_type_value = median(value), # 筛选排除当前type的value并计算中位数 median_non_type_value = median(filter(first(all_data), type != cur_group()$type)$value), .groups = "drop" )
代码说明
group_by(id)+mutate(all_data = list(tibble(type, value))):把当前id下的所有数据打包成列表,方便后续跨分组调用;group_by(id, type, .add = TRUE):保留原有id分组的同时,新增type分组维度;median_type_value = median(value):和原有代码逻辑一致,计算当前type分组内的中位数;median_non_type_value = median(filter(first(all_data), type != cur_group()$type)$value):从全量数据中过滤掉当前type的行,提取剩余value计算中位数,cur_group()$type用于获取当前分组的type标识。
运行上述代码即可得到符合预期的输出结果。
内容的提问来源于stack exchange,提问作者deman23
相关产品推荐
相关产品推荐

