R语言用dplyr、tidyr实现宽表转长表去重及bind_rows保留列名
解决方案
核心使用tidyr::pivot_longer的names_pattern+*.value*特殊参数实现,无需循环或手动拆分数据,可直接按规则匹配成对字段生成目标长表。
针对你提供的测试样例(列名为x1/y1/x2/y2格式)
library(tidyverse) # 你的测试数据 df.trial <- data.frame(x1 = seq(10), y1 = runif(10), x2 = seq(11,20), y2 = runif(10)) # 转换代码 df_result <- df.trial %>% pivot_longer( cols = everything(), # 正则拆分列名:第一组匹配x/y,第二组匹配组编号 names_pattern = "(.)(\\d+)", # .value表示把第一分组匹配的内容作为新列名,第二分组内容存入「属性名」列 names_to = c(".value", "属性名") )
输出结果无重复数据,结构如下:
| 属性名 | x | y |
|---|---|---|
| 1 | 1 | 0.345... |
| 2 | 11 | 0.782... |
| 1 | 2 | 0.123... |
| 2 | 12 | 0.564... |
| ... | ... | ... |
通用适配「属性.x/属性.y」格式的列名
如果你的实际字段是身高.x/身高.y、宽度.x/宽度.y这类结构,只需调整正则规则即可:
# 示例数据 df_attr <- data.frame( 身高.x = c(175, 180, 165), 身高.y = c(65, 72, 55), 体重.x = c(30, 35, 28), 体重.y = c(12, 15, 10) ) # 转换代码 df_attr_result <- df_attr %>% pivot_longer( cols = everything(), # 按点拆分列名:第一组为属性名,第二组为x/y names_pattern = "(.*)\\.(.*)", names_to = c("属性名", ".value") )
原写法出错原因
你之前两次调用pivot_longer没有绑定同组x/y的对应关系,会生成笛卡尔积导致重复条目;手动拆分再bind_rows的方式适配性差,分组多的时候容易出错。
内容的提问来源于stack exchange,提问作者TDLemonNovecento
相关产品推荐
相关产品推荐

