如何在pivot_longer中结合names_pattern使用正则表达式整理数据
解决R语言数据框宽转长格式问题
针对你提供的宽格式数据框,要转换为目标长格式,pivot_longer完全适用,关键是正确使用正则表达式拆分列名中的指标类型和时间索引。以下是具体实现步骤:
1. 核心思路
你的列名分为三类:
Weight_t1/t2/...:体重指标,时间后缀为t+数字year1/2/...:年份指标,时间后缀为数字LENGTHt1/t2/...:身高指标,时间后缀为t+数字
需要统一提取出指标名称和时间数字,利用tidyr的.value特殊参数,直接将同一时间点的三个指标合并为一行。
2. 完整代码
library(tidyr) library(dplyr) # 你的原始数据框 ID <- c("A01","B20","C3","D4") Nb_data <- c(2,2,2,3) Weight_t1 <- c(70,44,98,65) Weight_t2 <- c(75,78,105,68) Weight_t3 <- c(72,52,107,NA) year1 <- c(20,28,32,50) year2 <- c(28,32,35,60) year3 <- c(29,35,38,NA) LENGTHt1 <- c(175,155,198,165) LENGTHt2 <- c(175,155,198,163) LENGTHt3 <- c(176,154,198,NA) df <- data.frame(ID,Nb_data,Weight_t1,Weight_t2,Weight_t3,year1,year2,year3,LENGTHt1,LENGTHt2,LENGTHt3) # 转换为目标长格式 df_final <- df %>% pivot_longer( cols = -c(ID, Nb_data), # 保留ID和Nb_data列 names_to = c(".value", "time"), # .value表示第一组是列名,第二组是时间索引 names_pattern = "(Weight|year|LENGTH)(t?\\d+)", # 正则拆分:第一组是指标,第二组是时间(t可选+数字) values_drop_na = TRUE # 移除含NA的行 ) %>% rename(Year = year, Length = LENGTH) %>% # 统一列名大小写,匹配目标格式 arrange(ID, time) %>% # 按ID和时间排序 select(ID, Nb_data, Weight, Year, Length) # 调整列顺序 # 查看结果 print(df_final)
3. 代码解释
names_pattern = "(Weight|year|LENGTH)(t?\\d+)":正则表达式捕获两个组,第一组匹配指标名称,第二组匹配时间部分(t?表示可选的t,\\d+匹配1个以上数字)。names_to = c(".value", "time"):.value是pivot_longer的特殊参数,指定第一组捕获的内容作为新的列名(即Weight、year、LENGTH),第二组作为时间分组列。- 后续的
rename和select是为了统一列名格式,和目标输出对齐。
4. 输出结果示例
运行代码后,会得到如下格式的结果(和你提供的目标格式一致):
| ID | Nb_data | Weight | Year | Length |
|---|---|---|---|---|
| A01 | 2 | 70 | 20 | 175 |
| A01 | 2 | 75 | 28 | 175 |
| A01 | 2 | 72 | 29 | 176 |
| B20 | 2 | 44 | 28 | 155 |
| B20 | 2 | 78 | 32 | 155 |
| B20 | 2 | 52 | 35 | 154 |
| C3 | 2 | 98 | 32 | 198 |
| C3 | 2 | 105 | 35 | 198 |
| C3 | 2 | 107 | 38 | 198 |
| D4 | 3 | 65 | 50 | 165 |
| D4 | 3 | 68 | 60 | 163 |
内容的提问来源于stack exchange,提问作者Nic
相关产品推荐
相关产品推荐

