如何将含多时间点变量的宽格式DataFrame转换为长格式?
宽格式转长格式解决方案(tidyr::pivot_longer)
假设你的数据框结构如下(含示例数据):
library(tidyverse) # 构造示例数据 df <- tibble( id = c(1, 2), cpr0 = c(10, 15), cpr12 = c(12, 16), cpr24 = c(14, 18), cf0 = c(5, 7), cf12 = c(6, 8), cf24 = c(7, 9), h0 = c(170, 175), h12 = c(170, 175), h24 = c(172, 176), m0 = c(70, 72), m12 = c(68, 71), m24 = c(65, 69) )
要实现你需要的长格式转换,核心是利用pivot_longer的正则匹配分组功能,精准拆分变量名中的前缀(cpr/cf/h/m)和时间后缀(0/12/24):
df_long <- df %>% pivot_longer( cols = -id, # 保留id列,转换其他所有列 names_pattern = "(\\w+)(\\d+)", # 正则表达式:第一组匹配变量名,第二组匹配时间数字 names_to = c(".value", "time"), # .value表示将第一组作为新列名,第二组作为time列取值 values_drop_na = TRUE # 可选:删除含NA的行(如果存在) ) %>% mutate(time = as.integer(time)) # 将time转换为数值型(默认是字符类型)
参数说明
cols = -id:指定仅排除id列,其余列参与宽转长操作names_pattern = "(\\w+)(\\d+)":正则分为两个捕获组:(\\w+):匹配变量名前缀(如cpr、cf、h、m)(\\d+):匹配时间后缀(0、12、24)
names_to = c(".value", "time"):.value是特殊关键字,用于将第一捕获组内容设为新列名;第二捕获组内容存入time列
转换后的df_long结构如下:
# A tibble: 6 × 6 id time cpr cf h m <dbl> <int> <dbl> <dbl> <dbl> <dbl> 1 1 0 10 5 170 70 2 1 12 12 6 170 68 3 1 24 14 7 172 65 4 2 0 15 7 175 72 5 2 12 16 8 175 71 6 2 24 18 9 176 69
如果之前尝试失败,大概率是正则表达式匹配不准确,或names_to参数使用有误。针对你描述的cpr0、cf12这类命名格式,上述正则表达式完全适用。
内容的提问来源于stack exchange,提问作者Samuel Leal
相关产品推荐
相关产品推荐

