You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用pivot_longer正确重塑含多组对应列的dataframe?

问题描述

有如下结构的data.frame:

structure(list(id = 1:3, class_1 = c(333105L, 241306L, 242309L
), class_2 = c(333190L, 241390L, 242390L), prob_1 = c(0.954687457602604, 
0.929992569797772, 0.89535783792201), prob_2 = c(0.0335731906988228, 
0.0573986241136788, 0.096986046671658)), row.names = c(NA, -3L
), class = "data.frame")

需要将该数据框重塑为指定格式:把class_1、class_2合并为class列,prob_1、prob_2合并为prob列,且同一id下class_1对应prob_1、class_2对应prob_2,目标格式如下:

idclassprob
13331050.954687457602604
13331900.0335731906988228
22413060.929992569797772
22413900.0573986241136788
32423090.89535783792201
32423900.096986046671658

尝试了两种pivot_longer写法均未得到正确结果:
写法1会将class和prob列合并到同一列:

df %>% 
  pivot_longer(matches("[[:digit:]]$", perl = T), names_to = "class", values_to = "val") %>% 

写法2返回错误格式:

df %>% 
  pivot_longer(starts_with("class"), names_to = "class", values_to = "val_class") %>% 
  pivot_longer(starts_with("prob"), names_to = "prob", values_to = "val_prob")

请问如何实现正确的重塑?


解决方案

可以利用pivot_longer的多列分组匹配功能,通过提取列名中的数字后缀关联对应class和prob列,具体代码如下:

library(tidyr)

df %>%
  pivot_longer(
    cols = -id,  # 保留id列,其余列参与重塑
    names_to = c(".value", "group"),  # .value保留列名前缀作为新列名,group提取数字后缀
    names_pattern = "(class|prob)_(\\d)"  # 正则拆分列名为前缀(class/prob)和数字后缀
  ) %>%
  select(-group)  # 移除中间生成的group列

代码说明

  • cols = -id:明确只对除id外的列做重塑操作。
  • names_to = c(".value", "group"):.value是tidyr的特殊参数,会把匹配正则第一个捕获组的内容作为新列名;group用来暂存数字后缀,确保同后缀的class和prob对应。
  • names_pattern = "(class|prob)_(\\d)":精准拆分列名,保证class_1和prob_1、class_2和prob_2分别归为同一组。
  • select(-group):如果不需要中间的group辅助列,执行此步删除即可得到目标格式。

另外也可以用data.table包的melt函数实现:

library(data.table)

setDT(df)
melt(df, 
     measure.vars = patterns("^class", "^prob"), 
     value.name = c("class", "prob"))[, variable := NULL][]

内容的提问来源于stack exchange,提问作者Jeparov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:35:23