R语言:按Company与Job聚合后转宽表的实现问题求助
解决R语言中重复分组的长转宽问题
嘿,这个问题我熟!你之所以遇到错误,核心原因是你的数据里存在重复的Company+Job组合——reshape和spread都要求每个分组(Company+Job)是唯一的,不然就不知道该保留哪个值,要么给警告只取第一行,要么直接报错。
解决思路很简单:先把同一Company+Job的Value求和,消除重复组合,再转成宽格式就行。下面给你两种常用的实现方法:
方法一:使用tidyverse工具链(推荐)
dplyr负责分组求和,tidyr的pivot_wider(比旧版的spread更灵活)负责转宽格式,还能直接填充缺失值为0:
library(tidyverse) # 你的原始数据 df1 <- data.frame( "Company" = c(1, 1, 1, 1, 2, 2, 3, 3, 3, 4), "Job" = c(1,4,5,1,5,5,1,2,3,4), "Value" = c(2.3,3,4.1,5.4,7.3,4.2,3.1,4,5,1.1) ) # 第一步:按Company和Job分组,对Value求和 df_sum <- df1 %>% group_by(Company, Job) %>% summarise(Value = sum(Value), .groups = "drop") # 第二步:转换为宽格式,自动生成Job1/Job2列名,缺失值填0 df2 <- df_sum %>% pivot_wider( id_cols = Company, names_from = Job, names_prefix = "Job", values_from = Value, values_fill = 0 ) # 输出结果 print(df2)
运行后就能得到你想要的结果:每个Company一行,不同Job作为列,对应Value求和,没有的Job值自动填0。
方法二:使用Base R实现
如果不想加载额外包,用Base R的aggregate先聚合求和,再用reshape转宽:
# 你的原始数据 df1 <- data.frame( "Company" = c(1, 1, 1, 1, 2, 2, 3, 3, 3, 4), "Job" = c(1,4,5,1,5,5,1,2,3,4), "Value" = c(2.3,3,4.1,5.4,7.3,4.2,3.1,4,5,1.1) ) # 第一步:聚合求和,消除重复的Company+Job组合 df_sum_base <- aggregate(Value ~ Company + Job, data = df1, sum) # 第二步:转宽格式 df2_base <- reshape( df_sum_base, idvar = "Company", timevar = "Job", direction = "wide", v.names = "Value" ) # 调整列名(把Value.1改成Job1),并将NA替换为0 colnames(df2_base) <- gsub("Value\\.", "Job", colnames(df2_base)) df2_base[is.na(df2_base)] <- 0 # 输出结果 print(df2_base)
为什么之前的代码会出错?
- 用
reshape时,警告提示“multiple rows match for Job=1: first taken”,说明它发现了重复的Company+Job组合,只能默认取第一行的值,不是你要的求和结果; - 用
spread时,错误提示“Each row of output must be identified by a unique combination of keys”,直接明确要求每个分组必须唯一,所以无法处理重复组合。
先聚合再转宽,就能完美解决这个问题啦!
内容的提问来源于stack exchange,提问作者C. Toni
相关产品推荐
相关产品推荐

