如何用pivot_longer/melt映射AGE与SCORE列转换纵向数据框?
解决方案
方法一:使用tidyr::pivot_longer(推荐)
这是最简洁的方式,通过正则匹配直接实现AGE与SCORE列的对应映射:
# 先构造示例数据框(替换成你的实际数据) df <- data.frame( ID = c(1, 2, 3), AGE1 = c(10, 12, 11), AGE2 = c(13, 14, 15), AGE3 = c(16, 17, 18), AGE4 = c(19, 20, 21), SCORE1 = c(80, 85, 78), SCORE2 = c(82, 88, 80), SCORE3 = c(85, 90, 83), SCORE4 = c(88, 92, 85) ) library(tidyr) # 转换为适合折线图的长格式 long_df <- df %>% pivot_longer( cols = -ID, # 排除ID列,处理其余所有列 names_to = c(".value", "wave"), # .value保留前缀作为新列名,wave存储数字后缀 names_pattern = "(AGE|SCORE)(\\d)" # 正则匹配提取前缀(AGE/SCORE)和数字编号 )
转换后的数据结构:
| ID | wave | AGE | SCORE |
|---|---|---|---|
| 1 | 1 | 10 | 80 |
| 1 | 2 | 13 | 82 |
| 1 | 3 | 16 | 85 |
| ... | ... | ... | ... |
方法二:使用reshape2::melt
如果习惯用melt,可以拆分年龄和分数列后合并:
library(reshape2) # 拆分年龄列 age_df <- melt(df, id.vars = "ID", measure.vars = paste0("AGE", 1:4), variable.name = "wave", value.name = "AGE") # 拆分分数列 score_df <- melt(df, id.vars = "ID", measure.vars = paste0("SCORE", 1:4), variable.name = "wave", value.name = "SCORE") # 去除wave列的前缀,保留数字编号 age_df$wave <- gsub("AGE", "", age_df$wave) score_df$wave <- gsub("SCORE", "", score_df$wave) # 合并得到对应映射的长格式 long_df_melt <- merge(age_df, score_df, by = c("ID", "wave"))
绘制折线图示例
转换完成后,直接用ggplot绘制折线图:
library(ggplot2) ggplot(long_df, aes(x = AGE, y = SCORE, group = ID, color = factor(ID))) + geom_line(linewidth = 1) + geom_point(size = 2) + labs(x = "年龄", y = "分数", color = "个体ID") + theme_minimal()
内容的提问来源于stack exchange,提问作者bruteforce
相关产品推荐
相关产品推荐

