如何整理多变量多条目数据集以在R中绘制关联图表?
解决宽格式数据转长格式的重复问题
你两次用gather导致重复的原因很直接:第一次转换后每个ID对应3行(3个时间点的年龄),第二次转换时每一行又会和3个体重行形成笛卡尔积组合,最终每个ID会生成9行冗余数据,这显然不是你需要的对应关系。
正确的思路是保留时间点的匹配关系,让同一时间点的age和weight落在同一行,下面是两种可行的解决方法:
方法1:用pivot_longer(tidyr 1.0+推荐用法)
这个函数可以通过正则表达式直接拆分列名里的变量名和时间点,自动匹配同时间点的age和weight:
library(tidyverse) # 你的原始模拟数据 ID <- c(1, 2, 3) age1 <- c(10, 15, 20) age2 <- c(11, 16, 21) age3 <- c(12, 17, 22) weight1 <- c(30, 50, 60) weight2 <- c(35, 55, 65) weight3 <- c(38, 56, 67) df <- data.frame(ID, age1, age2, age3, weight1, weight2, weight3) # 转换为目标格式 df_clean <- df %>% pivot_longer( cols = -ID, # 仅处理非ID列 names_to = c(".value", "time_point"), # .value提取变量名(age/weight),time_point提取时间点数字 names_pattern = "(age|weight)(\\d+)" # 正则拆分列名:第一部分是变量类型,第二部分是时间点 )
转换后每个ID对应3行,每行是同一时间点的年龄和体重,完全没有冗余:
# A tibble: 9 × 4 ID time_point age weight <dbl> <chr> <dbl> <dbl> 1 1 1 10 30 2 1 2 11 35 3 1 3 12 38 4 2 1 15 50 5 2 2 16 55 6 2 3 17 56 7 3 1 20 60 8 3 2 21 65 9 3 3 22 67
方法2:旧版tidyr用gather+separate+spread组合
如果你的tidyr版本较低没有pivot_longer,可以用这套组合操作实现相同效果:
df_clean_old <- df %>% gather(key = var_time, value = value, -ID) %>% # 先将所有非ID列转成长格式 separate(var_time, into = c("variable", "time_point"), sep = "(?<=[a-z])(?=[0-9])") %>% # 拆分列名为变量和时间点 spread(key = variable, value = value) # 将变量名转回列,匹配对应时间点的数值
后续绘图示例
转换完成后,就可以轻松绘制所有ID的趋势图,比如:
所有ID的年龄随时间变化曲线
ggplot(df_clean, aes(x = time_point, y = age, group = ID, color = factor(ID))) + geom_line() + labs(x = "时间点", y = "年龄", color = "ID")
所有ID的体重随时间变化曲线
ggplot(df_clean, aes(x = time_point, y = weight, group = ID, color = factor(ID))) + geom_line() + labs(x = "时间点", y = "体重", color = "ID")
内容的提问来源于stack exchange,提问作者y.a
相关产品推荐
相关产品推荐

