如何在多变量聚合下将长格式转宽格式并保留原始重复行
解决长格式转宽格式并保留重复行的问题
嘿,我来帮你搞定这个长转宽还得保留原始重复行的需求!先把你的测试数据完整跑出来,方便我们后续操作:
# 构建测试数据 id = c(rep(1,5), rep(2,5)) type = factor(c(1L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L), labels = c('pay','inv')) lett = c('a', 'b', 'a_inv','a_inv', 'b_inv', 'c', 'c', 'd', 'd', NA) numb = c(30, 30, -10, -20, -30, -20, -20, 20, 20, NA) abs_numb = abs(numb) test = data.frame(id, type, lett, numb, abs_numb)
你的核心诉求是在多变量聚合的前提下转宽格式,但要保留原始的重复行——普通的pivot_wider(或者旧版的spread)会自动对相同分组的行做聚合操作,这显然不符合你的要求。所以关键在于:先给每个分组内的重复行添加唯一标识,这样转宽时就能精准保留每一行的原始信息。
下面是具体的解决方案,用dplyr+tidyr就能轻松实现:
library(dplyr) library(tidyr) test_wide <- test %>% # 按id和type分组,给每组内的行添加序号,用来区分重复项 group_by(id, type) %>% mutate(row_id = row_number()) %>% ungroup() %>% # 转宽格式:把type拆成pay/inv列,对应保留lett、numb、abs_numb的取值 pivot_wider( id_cols = c(id, row_id), # 用id+row_id作为唯一标识 names_from = type, values_from = c(lett, numb, abs_numb), names_sep = "_" # 列名用下划线区分类型和原始列名 ) %>% # 调整列顺序,让结构更清晰(可选操作) select(id, starts_with("pay"), starts_with("inv"), row_id) # 查看最终结果 print(test_wide)
结果说明
生成的宽格式数据里,每个原始的重复行都被完整保留了:
row_id用来标记同一id下同一type内的行序号,确保转宽时不会合并重复行- 列名比如
pay_lett、inv_numb清晰对应原始长格式里的字段和类型 - 如果不需要
row_id,在最后一步加上select(-row_id)即可删除
内容的提问来源于stack exchange,提问作者outboundbird
相关产品推荐
相关产品推荐

