如何用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,目标格式如下:
| id | class | prob |
|---|---|---|
| 1 | 333105 | 0.954687457602604 |
| 1 | 333190 | 0.0335731906988228 |
| 2 | 241306 | 0.929992569797772 |
| 2 | 241390 | 0.0573986241136788 |
| 3 | 242309 | 0.89535783792201 |
| 3 | 242390 | 0.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
相关产品推荐
相关产品推荐

