R语言中将多行Dataframe转换为多列的实现问题
嘿,我太懂你这困扰了——想用类似spread()的功能转置数据,但因为每个(Company、Loc、Type)组里的Spec数量不固定(最多20条),直接用spread()根本搞不定对吧?别慌,咱们用tidyr的新工具pivot_wider()(它是spread()的升级版,灵活多了)配合分组编号就能完美解决!
第一步:先构造个和你数据类似的示例(方便演示)
library(tidyverse) # 模拟你的原始数据 df <- tibble( Company = rep("100000012", 4), Loc = rep(104, 4), Type = rep(51, 4), Spec = c(363, 254, 178, 921) ) # 再加一个Spec数量更少的组 df <- bind_rows(df, tibble( Company = "100000013", Loc = 105, Type = 52, Spec = c(456, 789) ))
第二步:给每个组内的Spec添加序号
核心思路是:先按你的唯一标识(Company、Loc、Type)分组,给每组里的每一条Spec记录编个号(比如第1条就是Spec_1,第2条就是Spec_2...),这样转置的时候就有了明确的列名依据:
df_with_seq <- df %>% group_by(Company, Loc, Type) %>% mutate(spec_column = paste0("Spec_", row_number())) %>% ungroup()
第三步:用pivot_wider完成转置
这一步就简单了,直接指定分组列作为id,用刚才生成的序号列作为新列名,Spec作为列值:
final_result <- df_with_seq %>% pivot_wider( id_cols = c(Company, Loc, Type), names_from = spec_column, values_from = Spec )
看看最终效果
运行完上面的代码,你会得到这样的结果:
A tibble: 2 × 6Company Loc Type Spec_1 Spec_2 Spec_3 Spec_4
1 100000012 104 51 363 254 178 921
2 100000013 105 52 456 789 NA NA
看到没?每个组的Spec都变成了对应序号的列,组内Spec数量不足的地方自动填充NA,完全符合你“最多20条”的需求——哪怕某个组有20条Spec,row_number()也会自动生成到Spec_20,pivot_wider会把这些列都列出来。
为什么spread()不行?因为spread()要求你提前指定固定的key值,但你的每组Spec数量不固定,没法提前列全所有可能的列名,而先加序号再用pivot_wider就完美解决了这个动态列名的问题!
内容的提问来源于stack exchange,提问作者Joe Hafer

