求助:嵌套家庭数据中用ggplot2绘制Spaghetti图的错误排查
排查ggplot2绘制嵌套数据Spaghetti图的问题
我想用ggplot2绘制得分随研究时间点(wave)变化的Spaghetti图,这类图在简单数据集里很容易实现,但这次处理的是按家庭(fam)和同卵/异卵(zyg)嵌套的数据,我只关注每个家庭的第一个MZ个体,却没法得到每条个体对应一条时间线的预期效果。
模拟数据
# 模拟嵌套数据 set.seed(123) n_fam <- 20 n_wave <- 4 # 生成家庭数据 fam_data <- data.frame( fam = rep(1:n_fam, each = 2), zyg = rep(c("MZ", "DZ"), n_fam), id = 1:(2*n_fam) ) # 生成时间点得分数据 wave_data <- expand.grid(id = fam_data$id, wave = 1:n_wave) wave_data$score <- rnorm(nrow(wave_data), mean = 50, sd = 10) # 合并数据 data <- merge(fam_data, wave_data, by = "id")
当前代码
library(ggplot2) # 筛选每个家庭的第一个MZ个体 filtered_data <- data %>% filter(zyg == "MZ") %>% group_by(fam) %>% slice(1) %>% ungroup() # 绘制Spaghetti图 ggplot(filtered_data, aes(x = wave, y = score)) + geom_line() + labs(x = "研究时间点", y = "得分", title = "MZ个体得分随时间变化Spaghetti图")
问题分析
核心问题是缺少分组映射:ggplot2默认会将所有数据点归为一组,因此只会画出一条汇总线条,而非每个个体独立的时间线。你的筛选逻辑是正确的(slice(1)能取到每个家庭的第一个MZ个体),但绘图时没有指定按id分组。
修正方案
在aes()中添加group = id,明确告诉ggplot2按照个体ID分组连线:
library(ggplot2) library(dplyr) # 筛选每个家庭的第一个MZ个体 filtered_data <- data %>% filter(zyg == "MZ") %>% group_by(fam) %>% slice(1) %>% ungroup() # 修正后的绘图代码 ggplot(filtered_data, aes(x = wave, y = score, group = id)) + geom_line() + labs(x = "研究时间点", y = "得分", title = "MZ个体得分随时间变化Spaghetti图")
如果需要直观区分不同个体的线条,可以增加颜色映射:
ggplot(filtered_data, aes(x = wave, y = score, group = id, color = factor(id))) + geom_line() + labs(x = "研究时间点", y = "得分", title = "MZ个体得分随时间变化Spaghetti图", color = "个体ID") + theme(legend.position = "right")
关键说明
group = id是实现个体独立时间线的核心,确保每个ID对应的多个时间点数据被单独连线。- 确认筛选后的数据中,每个
id对应多个wave的记录(模拟数据中每个个体有4个时间点,满足要求)。
内容的提问来源于stack exchange,提问作者lf_araujo
相关产品推荐
相关产品推荐

