如何针对不同列组合使用pivot_wider实现指定宽表转换?
解决方案
你的问题出在同时将xy和xz作为names_from的参数,导致生成了两者的交叉组合列,而非分别对应y和z的独立列。可以通过拆分处理再合并的方式实现需求:
方法一:分步处理后合并(直观易懂)
library(tidyr) library(dplyr) # 原始数据集 df <- data.frame(xy=c("A","A","B","B","C","C"), xz=c("D","E","F","G","H","I"), y=c(1,2,3,4,5,6), z=c(1,2,3,4,5,6)) # 处理xy与y的分组求和并转宽 y_wide <- df %>% group_by(xy) %>% summarise(y_sum = sum(y)) %>% pivot_wider(names_from = xy, values_from = y_sum, names_prefix = "y.") # 处理xz与z的转宽(因xz唯一,sum不改变原值) z_wide <- df %>% pivot_wider(names_from = xz, values_from = z, names_prefix = "z.") # 合并两个结果 result <- bind_cols(y_wide, z_wide)
执行后得到的result就是你想要的输出:
# A tibble: 1 × 9 y.A y.B y.C z.D z.E z.F z.G z.H z.I <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 3 7 11 1 2 3 4 5 6
方法二:通过长格式中转(更简洁)
如果想一步完成,可以先将数据转为长格式,再按变量类型分别匹配分组列:
df %>% pivot_longer(cols = c(y, z), names_to = "var", values_to = "val") %>% group_by(var, across(c(xy, xz))) %>% summarise(val = sum(val), .groups = "drop") %>% pivot_wider( names_from = c(var, ifelse(var == "y", xy, xz)), values_from = val, names_sep = "." )
为什么原代码不符合预期?
原代码中names_from=c(xy,xz)会让tidyr生成xy和xz所有取值的交叉组合作为列名(比如y.A.D、y.A.E),这完全偏离了你“分别将xy对应y、xz对应z转宽”的需求。
内容的提问来源于stack exchange,提问作者HappyPy
相关产品推荐
相关产品推荐

