논문 품질 그래프 만들기 (ggplot2)
논문에 넣는 그래프는 발표용 슬라이드 그래프와 다릅니다. 화려함보다 정확성, 가독성, 인쇄 품질이 우선입니다. Nature, Science 같은 저널의 그래프 제출 가이드라인을 보면 공통적인 요구사항이 있습니다.
저널 제출용 그래프 기준
# 저널 공통 요구사항
# 해상도 : 300 DPI 이상 (인쇄 기준), 600 DPI 권장 (선 그래프)
# 형식 : TIFF, EPS, PDF 선호 (PNG도 허용하는 곳 많음)
# 크기 : 단단 폭 8.5 cm, 양단 폭 17.4 cm (일반적 기준)
# 폰트 : 8~10 pt, 산세리프(Arial, Helvetica)
# 색상 : 흑백 인쇄에서도 구분되어야 함 (패턴 또는 흑백 친화적 팔레트)
# 테마 : 배경 없음, 격자선 최소화
theme_classic() — 논문 기본 테마
library(ggplot2)
# theme_classic()이 논문 그래프의 출발점
# 흰 배경, 위·오른쪽 테두리 없음, 격자선 없음
ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
theme_classic()
# theme_bw()는 격자선 있는 버전 — 데이터가 많을 때 유용
# theme_minimal()은 테두리도 없는 최소한 버전
# 어떤 저널에 낼지에 따라 선택합니다
축과 범례 포매팅
# 완성도 높은 논문용 산점도
p <- ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 2.5, alpha = 0.8) +
geom_smooth(method = "lm", se = FALSE, linewidth = 0.8) +
# 축 제목과 범례 레이블
labs(
title = NULL, # 논문 본문에 그림 설명을 달므로 제목 불필요
x = "Vehicle Weight (1,000 lbs)",
y = "Fuel Efficiency (mpg)",
color = "Cylinders"
) +
# 흑백 친화적 색상 팔레트
scale_color_manual(values = c("4" = "#000000",
"6" = "#666666",
"8" = "#AAAAAA")) +
# 축 범위와 눈금
scale_x_continuous(limits = c(1.5, 5.5),
breaks = seq(2, 5, by = 1)) +
scale_y_continuous(limits = c(8, 36),
breaks = seq(10, 35, by = 5)) +
# 논문용 테마 커스터마이징
theme_classic(base_size = 11) +
theme(
# 축 제목
axis.title = element_text(size = 10, face = "plain"),
axis.text = element_text(size = 9, color = "black"),
axis.line = element_line(linewidth = 0.5),
axis.ticks = element_line(linewidth = 0.5),
# 범례
legend.title = element_text(size = 9),
legend.text = element_text(size = 8),
legend.position = "top", # 위치: "top", "bottom", "left", "right"
legend.key.size = unit(0.4, "cm"),
# 여백
plot.margin = margin(5, 10, 5, 5, unit = "mm")
)
p
한글 폰트: showtext 패키지
저널에 따라 한글 논문도 많습니다. R의 기본 그래픽 장치는 한글 폰트를 제대로 표시하지 못할 때가 많습니다. showtext 패키지로 해결합니다.
install.packages("showtext")
library(showtext)
# 구글 폰트 추가 (인터넷 연결 필요)
font_add_google("Noto Sans KR", "notosans")
font_add_google("Nanum Gothic", "nanumgothic")
# showtext 활성화 — 이후 모든 ggplot에 적용됨
showtext_auto()
# 한글 그래프
ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point(color = "steelblue", size = 2.5) +
labs(
x = "차체 무게 (1,000 lbs)",
y = "연비 (mpg)",
caption = "출처: Motor Trend, 1974"
) +
theme_classic(base_size = 12, base_family = "nanumgothic")
# 시스템 폰트 직접 등록 (오프라인 환경)
font_add("malgun", regular = "malgun.ttf") # 맑은고딕 (Windows)
# macOS: font_add("applegothic", regular = "/System/Library/Fonts/AppleGothic.ttf")
showtext_auto()
ggsave()로 고품질 이미지 저장하기
# ggsave(파일명, 플롯객체, width, height, dpi, units)
ggsave(
filename = "fig1_weight_mpg.tiff",
plot = p,
width = 8.5, # 단단(single column) 폭
height = 7,
units = "cm",
dpi = 300
)
# 양단(double column) 크기로 저장
ggsave(
filename = "fig1_weight_mpg_wide.tiff",
plot = p,
width = 17.4,
height = 10,
units = "cm",
dpi = 300
)
# PDF로 저장 (벡터 형식 — 크기에 무관하게 선명)
ggsave(
filename = "fig1_weight_mpg.pdf",
plot = p,
width = 8.5,
height = 7,
units = "cm"
)
여러 그래프 조합: patchwork
논문에서는 Figure 1A, 1B처럼 여러 패널을 하나의 그림으로 묶어서 제출하는 경우가 많습니다.
install.packages("patchwork")
library(patchwork)
# 개별 그래프 생성
p1 <- ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point(color = "steelblue") +
labs(title = "(A)", x = "Weight (1,000 lbs)", y = "mpg") +
theme_classic(base_size = 10)
p2 <- ggplot(mtcars, aes(x = hp, y = mpg)) +
geom_point(color = "tomato") +
labs(title = "(B)", x = "Horsepower", y = "mpg") +
theme_classic(base_size = 10)
p3 <- ggplot(mtcars, aes(x = factor(cyl), y = mpg)) +
geom_boxplot(fill = "lightgray") +
labs(title = "(C)", x = "Cylinders", y = "mpg") +
theme_classic(base_size = 10)
# 조합 방법
(p1 | p2) / p3 # 위에 두 개, 아래에 하나
p1 + p2 + p3 +
plot_layout(ncol = 3) # 3열 배치
# 저장
combined <- (p1 | p2) / p3
ggsave("fig1_combined.tiff", combined,
width = 17.4, height = 12, units = "cm", dpi = 300)
색상 선택 가이드
# 색맹 친화적 팔레트 (Okabe & Ito 팔레트)
okabe_ito <- c("#E69F00", "#56B4E9", "#009E73",
"#F0E442", "#0072B2", "#D55E00", "#CC79A7")
# viridis — 흑백 인쇄에서도 구분 가능
library(ggplot2)
scale_fill_viridis_d() # 이산형 변수
scale_fill_viridis_c() # 연속형 변수
# RColorBrewer — 범주별 대비 명확
install.packages("RColorBrewer")
library(RColorBrewer)
display.brewer.all()
scale_fill_brewer(palette = "Set2")
잘 만든 그래프 하나가 페이지 가득한 설명보다 효과적입니다. 처음부터 논문 기준으로 만들어두면 나중에 다시 작업할 필요가 없습니다.