如何对含多names_from与values_from列的dataframe执行pivot_wider?
解决方法
要实现你需要的宽表转换,得先把数据从宽表转成长表,统一处理p/s/t前缀的列,再重新转回宽表。具体步骤如下:
1. 加载所需工具
先确保安装并加载tidyr(属于tidyverse套件):
install.packages("tidyverse") library(tidyr)
2. 转成中间长表
把原始数据里带p/s/t前缀的列拆分,提取出「类别(p/s/t)」和「属性(code/saved/cost)」:
df_long <- df %>% pivot_longer( cols = -code, # 保留原始A1/A2这类code列,其他列参与转换 names_to = c("category", ".value"), # 列名拆成两部分:前缀存为category,后缀作为新列名 names_pattern = "(.)(code|saved|cost)" # 正则匹配:第一个字符是p/s/t,后面是code/saved/cost )
转换后df_long的结构示例:
| code | category | code_col | saved | cost |
|---|---|---|---|---|
| A1 | p | el | 10 | 20 |
| A1 | s | e1 | 10 | 20 |
| A1 | t | e2 | 10 | 20 |
| A2 | p | el | 10 | 20 |
3. 生成目标宽表
把code_col(原pcode/scode/tcode的取值)作为列名,将saved和cost对应填入单元格:
df_wide <- df_long %>% pivot_wider( id_cols = code, # 以原始code列为分组依据 names_from = code_col, # 用code_col的取值作为新列名前缀 values_from = c(saved, cost), # 把saved和cost的值填入对应列 names_glue = "{code_col}_{.value}" # 拼接列名,格式为「code值_属性」,比如el_saved )
最终结果示例
df_wide的部分内容如下:
| code | el_saved | el_cost | e1_saved | e1_cost | e2_saved | e2_cost | ng_saved | ng_cost | e3_saved | e3_cost |
|---|---|---|---|---|---|---|---|---|---|---|
| A1 | 10 | 20 | 10 | 20 | 10 | 20 | NA | NA | NA | NA |
| A2 | 10 | 20 | NA | NA | 10 | 20 | NA | NA | 10 | 20 |
| A3 | NA | NA | 10 | 30 | 10 | 30 | 10 | 30 | NA | NA |
单元格数值对应原始数据中该行p/s/t组内匹配code值的saved或cost,无匹配项的位置填充NA。
内容的提问来源于stack exchange,提问作者knick
相关产品推荐
相关产品推荐

