Ch 05. facet으로 다중 패널 만들기
한 차트에 여러 그룹을 색상으로 구분하면 비교가 가능하지만 한계가 있습니다. 그룹이 많아지면 색상이 뒤엉키고, 각 그룹 내의 분포를 세밀하게 보기 어렵습니다.
facet은 이 문제를 해결합니다. 하나의 차트를 그룹별로 나누어 소 차트(패널)를 만듭니다. 같은 축 스케일로 정렬되어 있어서 그룹 간 비교가 직관적입니다.
facet_wrap — 변수 하나로 패널 분할
가장 자주 쓰이는 facet 함수입니다. 하나의 범주형 변수를 기준으로 패널을 만들고, 자동으로 배치합니다.
library(tidyverse)
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(color = "steelblue", alpha = 0.6) +
facet_wrap(~ class) +
labs(
title = "클래스별 배기량과 연비",
x = "엔진 배기량 (리터)",
y = "고속도로 연비 (mpg)"
) +
theme_minimal()
~ class는 "class 변수를 기준으로 나누겠다"는 공식입니다. 차량 클래스 수(7개)만큼 패널이 만들어지고, ggplot2가 자동으로 행과 열을 배치합니다.
열 수 지정
ncol로 한 행에 몇 개의 패널을 배치할지 지정합니다.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(color = "steelblue", alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE, color = "tomato", linewidth = 0.7) +
facet_wrap(~ class, ncol = 3) +
labs(
title = "클래스별 배기량과 연비 (3열 배치)",
x = "배기량 (리터)",
y = "고속도로 연비 (mpg)"
) +
theme_minimal()
ncol = 3이면 3열로 정렬됩니다. nrow로 행 수를 지정할 수도 있습니다.
scales 인수 — 축 스케일 제어
기본적으로 모든 패널은 동일한 축 범위를 공유합니다. 그룹별 데이터 범위가 크게 다를 때는 scales 인수로 조정합니다.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(alpha = 0.6) +
facet_wrap(~ class, scales = "free") +
labs(
title = "클래스별 배기량과 연비 (축 자유 조정)",
x = "배기량 (리터)",
y = "고속도로 연비 (mpg)"
) +
theme_minimal()
scales 옵션 정리.
| 값 | 의미 |
|---|---|
"fixed" |
모든 패널이 동일한 축 (기본값) |
"free" |
X, Y축 모두 각 패널에 맞게 조정 |
"free_x" |
X축만 자유, Y축 고정 |
"free_y" |
Y축만 자유, X축 고정 |
scales = "free"는 패널 내 분포를 자세히 보고 싶을 때 유용합니다. 단, 그룹 간 절대적인 크기 비교는 어려워집니다. 목적에 따라 선택합니다.
facet_grid — 두 변수로 격자 패널
행과 열에 각각 다른 변수를 배치해 격자 형태의 패널을 만듭니다.
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point(alpha = 0.5, color = "steelblue") +
facet_grid(drv ~ cyl) +
labs(
title = "구동 방식 × 실린더 수별 배기량과 연비",
x = "배기량 (리터)",
y = "고속도로 연비 (mpg)"
) +
theme_minimal()
drv ~ cyl는 "행에 drv, 열에 cyl"을 배치하겠다는 뜻입니다.
- 행: drv (구동 방식 — f, r, 4) 3가지
- 열: cyl (실린더 수 — 4, 5, 6, 8) 4가지
총 12개의 패널이 격자로 배치됩니다. 빈 조합은 점이 없는 빈 패널로 표시됩니다.
행 또는 열 중 하나만 변수로 쓰려면 나머지에 .을 씁니다.
# 행만 변수로 분할
facet_grid(drv ~ .)
# 열만 변수로 분할
facet_grid(. ~ cyl)
facet_wrap vs facet_grid
| 항목 | facet_wrap | facet_grid |
|---|---|---|
| 변수 수 | 1개 | 1~2개 |
| 패널 배치 | 자동(ncol/nrow 조정 가능) | 격자 고정 |
| 빈 조합 | 표시하지 않음 | 빈 패널 표시 |
| 사용 목적 | 단일 범주 비교 | 두 범주의 교차 비교 |
두 변수의 조합 효과를 보고 싶다면 facet_grid, 한 변수를 간단히 나누어 보고 싶다면 facet_wrap이 적합합니다.
facet과 색상 함께 활용
facet으로 나누면서 색상으로 또 다른 변수를 표현하면 더 많은 정보를 담을 수 있습니다.
ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point(size = 2, alpha = 0.7) +
facet_wrap(~ year, ncol = 2) +
scale_color_brewer(palette = "Set2",
labels = c("4" = "사륜", "f" = "전륜", "r" = "후륜")) +
labs(
title = "연도별 배기량과 연비 비교",
x = "배기량 (리터)",
y = "고속도로 연비 (mpg)",
color = "구동 방식"
) +
theme_minimal() +
theme(legend.position = "bottom")
연도별로 패널을 나누고, 구동 방식을 색상으로 구분합니다. 1999년과 2008년의 패턴 변화를 비교할 수 있습니다.
그룹별 분포 비교 — facet 실전 예시
diamonds 데이터에서 컷 품질과 색상 등급에 따른 가격 분포를 비교합니다.
ggplot(diamonds, aes(x = price, fill = cut)) +
geom_histogram(binwidth = 1000, alpha = 0.8) +
facet_wrap(~ color, ncol = 4) +
scale_fill_brewer(palette = "Set2") +
scale_x_continuous(labels = scales::comma) +
labs(
title = "다이아몬드 색상 등급별 가격 분포",
x = "가격 (달러)",
y = "빈도",
fill = "컷 품질"
) +
theme_minimal() +
theme(
legend.position = "bottom",
axis.text.x = element_text(angle = 45, hjust = 1, size = 7)
)
scales::comma는 X축 숫자에 쉼표(1,000 단위)를 붙여줍니다. scales 패키지는 tidyverse에 포함되어 있습니다.
facet은 "같은 질문을 여러 그룹에 동시에 던지는" 도구입니다. 한 차트로는 보기 어려운 그룹 간 패턴 차이를 직관적으로 드러냅니다. 다음 챕터에서는 완성한 차트를 파일로 저장하고, 여러 차트를 하나로 조합하는 방법을 살펴봅니다.