如何用tidyr的pivot_longer高效转换含疾病列的宽格式数据集?
解决方案
核心方法
用tidyr::pivot_longer()配合正则表达式拆分列名,一次性完成宽转长并提取疾病类型,同时保留参与者背景信息列。
代码实现
假设你的数据框为df,10个背景信息列(比如age, gender, education等),疾病相关列均为[疾病前缀]_[问题标识]格式:
library(tidyr) library(dplyr) # 宽转长格式,提取疾病类型 df_long <- df %>% pivot_longer( # 排除背景列,只转换疾病相关列 cols = -c(age, gender, education, ...), # 替换为你的10个背景列名 # 正则拆分列名:捕获疾病前缀和问题标识 names_pattern = "(.*)_(.*)", # 拆分后的新列名称 names_to = c("disease_type", "question_label"), # 存储问题回答的列名 values_to = "response" )
参数详解
- cols:用
-c(...)排除背景列,也可以用matches("^(epi|ms|autism|...)_")直接匹配所有疾病列(括号内补全你的9种疾病前缀)。 - names_pattern:
(.*)_(.*)是核心,它将列名拆分为下划线前后两部分——第一部分就是你需要的疾病类型,第二部分是问题的标识(比如fam/exp)。 - names_to:指定拆分后生成的两个新列,
disease_type用来标识疾病组,question_label区分不同问题。
示例效果
假设原数据有背景列age、gender,疾病列epi_fam、epi_exp、autism_fam,转换后的数据结构如下:
| age | gender | disease_type | question_label | response |
|---|---|---|---|---|
| 28 | 男 | epi | fam | 1 |
| 28 | 男 | epi | exp | 0 |
| 35 | 女 | autism | fam | 1 |
适配特殊格式
如果部分列名带末尾点(比如ms_exp.),调整正则表达式即可兼容:
names_pattern = "(.*)_(.*?)\\.?" # 忽略列名末尾的点
内容的提问来源于stack exchange,提问作者Lea
相关产品推荐
相关产品推荐

