如何用pivot_longer函数转换分数与日期两组变量
解决方法:一次完成日期与分数的对应转换
你遇到的冗余问题是因为分步转换时没关联分数和日期的对应关系,导致产生了笛卡尔积。正确做法是用pivot_longer的多列匹配功能,一次性将分数和日期列按后缀数字关联转换。
示例代码
先构造一份模拟的宽格式数据:
library(tidyverse) # 模拟你的宽格式数据集 wide_data <- tibble( Patient = c("P001", "P002"), Score_1 = c(85, 78), Score_2 = c(90, 82), Score_3 = c(88, 80), Date_score1 = c("2023-01-05", "2023-02-10"), Date_score2 = c("2023-03-15", "2023-04-20"), Date_score3 = c("2023-05-25", "2023-06-30") )
执行转换:
long_data <- wide_data %>% pivot_longer( cols = -Patient, # 固定Patient列,处理其余所有列 names_to = c(".value", "test_idx"), # .value保留列名前缀作为新列名,test_idx提取后缀数字 names_pattern = "(Score|Date_score)(\\d)" # 正则匹配前缀和数字后缀 ) %>% # 调整列名和顺序,得到目标结构 select(Patient, Date = Date_score, Score)
关键逻辑说明
names_to = c(".value", "test_idx"):.value是pivot_longer的特殊参数,会把匹配到的列名前缀(比如Score、Date_score)作为新列名;test_idx提取列名后的数字(1/2/3),确保相同数字的分数和日期被分到同一行。names_pattern用正则表达式拆分列名:(Score|Date_score)匹配两种前缀,(\\d)匹配后面的数字,精准关联每个测试的分数和日期。
转换后的long_data结构就是你需要的:
| Patient | Date | Score |
|---|---|---|
| P001 | 2023-01-05 | 85 |
| P001 | 2023-03-15 | 90 |
| P001 | 2023-05-25 | 88 |
| P002 | 2023-02-10 | 78 |
| P002 | 2023-04-20 | 82 |
| P002 | 2023-06-30 | 80 |
内容的提问来源于stack exchange,提问作者Anandi Nobel
相关产品推荐
相关产品推荐

