如何将分组时间序列血清水平数据转为ggplot可视化图形?
Hey there! Let's break this down step by step since you're new to ggplot and figuring out the best way to visualize your longitudinal IL-6 data.
First, choosing between boxplots and dot/line plots:
- Boxplots are perfect for showing the distribution at each time point (they directly map to the median/IQR stats in your Table 2) — great for comparing overall group differences.
- Dot/line plots (connecting individual subjects across time) are ideal for showing individual changes over time, which adds context to the overall distribution boxplots show. I'd recommend using both together or picking based on what story you want to tell!
Let's start with your sample data, then build out the code you can extend easily.
Step 1: Prepare Your Data (Wide → Long Format)
ggplot works best with "long" data, so we'll reshape your wide columns into a tidy structure first:
# Install required packages if you haven't already: install.packages("tidyverse") library(tidyverse) # Your sample data df <- structure(list(a02rec = c(2925, 2461, 2887, 4132, 2734, 4176, 2158, 690, 4287, 2871), ND_IL_6I = c(156.475, 25.393, 5.20696, 29.448, 636.561, 16.7, 20.83028, 13.04912, 17.28, 30.686), ND_IL6_intermed = c(NA, NA, NA, NA, NA, 4.5048, 49.654, 5.1872, 23.8992, NA), IL_6_6mesesultimovalorITT = c(62.163, 59.278, 45.1272, 19.258, 17.689, 15.864, 16.0992, 22.88964, 14.748, 21.706), modeloterapia = structure(c(2L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L), .Label = c("pdse", "tcc"), class = "factor")), row.names = c(NA, 10L), class = "data.frame") # Reshape to long format & clean time point labels df_long <- df %>% pivot_longer( cols = starts_with(c("ND_IL_6", "IL_6")), # Grab all IL-6 related columns names_to = "time_point", values_to = "il6_level" ) %>% # Rename time points to readable labels mutate(time_point = case_when( time_point == "ND_IL_6I" ~ "Baseline", time_point == "ND_IL6_intermed" ~ "Post-Intervention", time_point == "IL_6_6mesesultimovalorITT" ~ "6-Month Follow-Up", TRUE ~ time_point )) %>% # Ensure time points plot in the correct order (not alphabetical) mutate(time_point = factor(time_point, levels = c("Baseline", "Post-Intervention", "6-Month Follow-Up")))
Step 2: Visualize Total Sample
Boxplot (Matches Your Table 2 Stats)
This plot directly shows median, IQR, and outliers — perfect for presenting the summary stats you calculated:
ggplot(df_long, aes(x = time_point, y = il6_level)) + geom_boxplot(fill = "#619CFF", alpha = 0.7) + geom_jitter(width = 0.1, color = "black", size = 1.5) + # Add individual points to show spread labs( title = "IL-6 Levels Across Time (Total Sample)", x = "Time Point", y = "IL-6 Serum Level" ) + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) # Rotate labels for readability
Dot-Line Plot (Shows Individual Changes)
This plot connects each subject's measurements across time to highlight individual trends:
ggplot(df_long, aes(x = time_point, y = il6_level, group = a02rec)) + geom_line(color = "gray", alpha = 0.5) + # Gray lines for individual trajectories geom_point(aes(color = time_point), size = 2) + labs( title = "Individual IL-6 Changes Across Time (Total Sample)", x = "Time Point", y = "IL-6 Serum Level" ) + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1), legend.position = "none") # Hide redundant legend
Step 3: Visualize By Treatment Group (PDSE vs TCC)
Grouped Boxplot (Color-Coded)
Compare distribution differences between groups at each time point:
ggplot(df_long, aes(x = time_point, y = il6_level, fill = modeloterapia)) + geom_boxplot(position = position_dodge(width = 0.8), alpha = 0.7) + geom_jitter(width = 0.1, color = "black", size = 1, position = position_dodge(width = 0.8)) + labs( title = "IL-6 Levels Across Time (By Treatment Group)", x = "Time Point", y = "IL-6 Serum Level", fill = "Treatment Group" ) + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Faceted Boxplot (Cleaner Side-by-Side Comparison)
Split into separate plots for each group to avoid clutter:
ggplot(df_long, aes(x = time_point, y = il6_level)) + geom_boxplot(fill = "#619CFF", alpha = 0.7) + geom_jitter(width = 0.1, color = "black", size = 1.5) + facet_wrap(~modeloterapia) + # Create one plot per treatment group labs( title = "IL-6 Levels Across Time (By Treatment Group)", x = "Time Point", y = "IL-6 Serum Level" ) + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Grouped Dot-Line Plot
Show individual trends separated by treatment group:
ggplot(df_long, aes(x = time_point, y = il6_level, group = a02rec, color = modeloterapia)) + geom_line(alpha = 0.5) + geom_point(size = 2) + labs( title = "Individual IL-6 Changes Across Time (By Treatment Group)", x = "Time Point", y = "IL-6 Serum Level", color = "Treatment Group" ) + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1))
Extending This Code
- Add 12-month follow-up: Include your 12-month column in the
pivot_longercolsargument, then update thetime_pointfactor levels. - Switch to TNF: Replace
starts_with(c("ND_IL_6", "IL_6"))with your TNF column pattern (e.g.,starts_with("TNF")) and adjust axis labels. - Customize appearance: Swap
theme_minimal()fortheme_bw(), or usescale_fill_manual()/scale_color_manual()to set your own colors. - Filter NAs: Add
drop_na(il6_level)to thedf_longpipeline if you want to exclude missing values entirely.
内容的提问来源于stack exchange,提问作者Bruno Montezano

