의료 데이터 시각화 — 논문 Figure 수준 그래프 만들기
…
한줄 요약
논문에 넣을 그래프는 예쁘면 안 된다 — 정보가 정확하고, 색이 색맹에게도 보이고, 300dpi여야 한다.
ggplot2 기초 문법
R의 ggplot2는 레이어를 쌓는 방식으로 그래프를 만든다.
library(ggplot2)
ggplot(data = df, aes(x = hba1c, y = fbs, color = group)) +
geom_point(alpha = 0.6, size = 2) +
geom_smooth(method = "lm", se = TRUE) +
labs(
title = "HbA1c와 공복혈당의 관계",
x = "당화혈색소 (%)",
y = "공복혈당 (mg/dL)",
color = "치료군"
) +
theme_bw()
data → aes() → geom_() → labs() → theme_() 순서가 기본 구조다.
의학 논문 필수 그래프 1: Box Plot
ggplot(df, aes(x = group, y = hba1c, fill = group)) +
geom_boxplot(outlier.shape = 21, width = 0.5) +
geom_jitter(width = 0.1, alpha = 0.3, size = 1) +
stat_compare_means(comparisons = list(c("치료", "대조")),
method = "wilcox.test") +
scale_fill_manual(values = c("#3C5488", "#E64B35")) +
theme_classic() +
theme(legend.position = "none")
jitter를 추가하면 데이터 분포가 보인다. 박스만 보여주는 것은 정보 은닉이라는 비판이 있다.
의학 논문 필수 그래프 2: Forest Plot
메타분석 또는 다변량 분석 결과를 시각화한다.
library(forestplot)
# 데이터 준비
tabletext <- cbind(
c("변수", "나이 (10년 증가)", "남성", "당뇨병", "흡연"),
c("HR", "1.34", "1.18", "1.52", "1.41"),
c("95% CI", "1.21–1.48", "0.97–1.43", "1.29–1.79", "1.19–1.67")
)
forestplot(
labeltext = tabletext,
mean = c(NA, 1.34, 1.18, 1.52, 1.41),
lower = c(NA, 1.21, 0.97, 1.29, 1.19),
upper = c(NA, 1.48, 1.43, 1.79, 1.67),
zero = 1,
col = fpColors(box = "#E64B35", line = "black")
)
의학 논문 필수 그래프 3: ROC Curve
library(pROC)
roc1 <- roc(df$outcome, df$model1_prob)
roc2 <- roc(df$outcome, df$model2_prob)
ggroc(list(Model1 = roc1, Model2 = roc2)) +
annotate("text", x = 0.3, y = 0.2,
label = paste0("Model 1 AUC = ", round(auc(roc1), 3))) +
annotate("text", x = 0.3, y = 0.1,
label = paste0("Model 2 AUC = ", round(auc(roc2), 3))) +
geom_abline(slope = 1, intercept = 1, linetype = "dashed") +
theme_bw()
Table 1 만들기
library(tableone)
vars <- c("age", "sex", "bmi", "hba1c", "sbp", "egfr")
catvars <- c("sex")
tab1 <- CreateTableOne(
vars = vars,
strata = "treatment",
data = df,
factorVars = catvars
)
print(tab1, showAllLevels = TRUE, smd = TRUE)
smd = TRUE로 표준화 평균 차이를 추가하면 매칭 연구의 balance 확인에 유용하다.
색상 선택: 색맹 친화적 팔레트
전체 인구의 약 8% (남성 기준)가 색각 이상이다. Red-Green을 함께 쓰면 안 된다.
# Okabe-Ito palette — 가장 널리 권장되는 색맹 친화 팔레트
okabe_ito <- c("#E69F00", "#56B4E9", "#009E73",
"#F0E442", "#0072B2", "#D55E00", "#CC79A7")
# 또는 viridis
library(viridis)
scale_fill_viridis_d() # 이산형
scale_fill_viridis_c() # 연속형
NEJM/Lancet 스타일 테마
library(ggthemes)
# NEJM 스타일
scale_color_nejm()
scale_fill_nejm()
# Lancet 스타일
scale_color_lancet()
scale_fill_lancet()
논문 제출용 고해상도 저장
ggsave(
filename = "figure1_survival.tiff",
plot = last_plot(),
width = 7,
height = 5,
dpi = 300,
compression = "lzw"
)
대부분의 의학 저널이 TIFF 300dpi를 요구한다. PDF는 벡터 형식으로 무한 확대 가능해서 심사자용으로 좋다.
핵심 정리
- ggplot2: data → aes → geom → labs → theme 레이어 구조
- Box plot에 jitter 추가: 데이터 분포 정직하게 표시
- Forest plot:
forestplot패키지, HR/OR 시각화 표준 - 색맹 친화: Okabe-Ito 또는 viridis 팔레트 사용
- 논문 제출: TIFF 300dpi, width 7인치 기준