R语言:如何新增合并指定行的记录且保留原数据(tidyverse优先)
问题
我有一份包含不同社会经济地位(SES)个体的纵向数据集,原始数据将SES划分为High、Mid、Mid Low、Low四类。我想要新增一行聚合Mid Low和Low两类的统计数据,同时保留原有的4类数据。目前我能通过代码获取聚合信息,但结果是以列的形式呈现,不知道怎么优雅地转成行数据。
数据集示例
library(dplyr) test_data <- tibble(month = c(rep(c("Jan"), 4), rep(c("Feb"), 4)), ses = c(rep(c("High", "Mid", "Mid Low", "Low"), 2)), total = c(10, 20, 20, 30, 9, 11, 40, 60), total_selected = c(9, 10, 8, 3, 8, 6, 8, 6)) %>% group_by(month, ses) %>% mutate(success_rate = total_selected/total)
当前代码(结果为列形式)
(test_data2 <- test_data %>% group_by(month) %>% mutate(three_ses_total = case_when( ses %in% c("High", "Mid") ~ total, ses %in% c("Mid Low", "Low") ~ (total[ses == "Mid Low"] + total[ses == "Low"]) ), three_ses_total_selected = case_when( ses %in% c("High", "Mid") ~ total_selected, ses %in% c("Mid Low", "Low") ~ (total_selected[ses == "Mid Low"] + total_selected[ses == "Low"]) ), three_ses_success_rate = case_when( ses %in% c("High", "Mid") ~ success_rate, ses %in% c("Mid Low", "Low") ~ three_ses_total_selected/three_ses_total )))
期望输出
(answer <- tibble(month = c(rep(c("Jan"), 5), rep(c("Feb"), 5)), ses = c(rep(c("High", "Mid", "Mid Low", "Low", "Mid Low and Low"), 2)), total = c(10, 20, 20, 30, 50, 9, 11, 40, 60, 100), total_selected = c(9, 10, 8, 3, 11, 8, 6, 8, 6, 14)) %>% group_by(month, ses) %>% mutate(success_rate = total_selected/total))
希望用dplyr、tidyr等tidyverse工具优雅解决。
解决方案
可以通过先聚合目标分组,再将聚合结果与原数据合并的方式实现,逻辑清晰且符合tidyverse风格:
- 从原数据中筛选出需要聚合的
Mid Low和Low两类,按month分组计算合并后的统计值,指定新的ses类别名称; - 将聚合得到的行数据与原数据集合并;
- 可选:按
month和ses排序,让结果结构更规整。
完整代码如下:
library(dplyr) # 生成聚合数据 aggregated_data <- test_data %>% filter(ses %in% c("Mid Low", "Low")) %>% group_by(month) %>% summarise( ses = "Mid Low and Low", total = sum(total), total_selected = sum(total_selected), success_rate = total_selected / total, .groups = "drop" ) # 合并原数据与聚合数据,按需排序 final_data <- test_data %>% bind_rows(aggregated_data) %>% arrange(month, ses) # 查看结果 final_data
代码解释
filter(ses %in% c("Mid Low", "Low")):筛选出需要聚合的两类数据;group_by(month) %>% summarise(...):按月份分组,计算合并后的total、total_selected和success_rate,并设置新的ses标签;bind_rows(aggregated_data):将聚合得到的行追加到原数据末尾;arrange(month, ses):按月份和SES类别排序,让结果与期望输出结构一致。
这种方式避免了原代码生成冗余列的问题,直接生成目标行数据,符合tidyverse"每行对应一个观测"的原则。
内容的提问来源于stack exchange,提问作者J.Sabree
相关产品推荐
相关产品推荐

