iBetter Books
수정

Ch 04. 색상과 테마 커스터마이징

차트를 만들었는데 뭔가 허전한 느낌이 든다면, 대부분 색상이나 스타일 때문입니다. 기본 테마의 회색 배경, 자동으로 배정된 원색 계열 색상은 탐색 단계에서는 충분하지만 보고서나 발표 자료로 쓰기에는 아쉽습니다.

이 챕터에서는 색상과 테마를 조정해 차트의 완성도를 높이는 방법을 다룹니다.

scale 함수의 구조

ggplot2에서 색상, 크기, 선 유형 같은 시각적 속성을 조정하는 함수는 scale_*() 계열입니다. 이름 규칙이 있습니다.

scale_{속성}_{유형}()
속성 유형 함수 예시
color manual scale_color_manual()
fill brewer scale_fill_brewer()
color continuous scale_color_continuous()
fill gradient scale_fill_gradient()
x continuous scale_x_continuous()
y log10 scale_y_log10()

color는 점·선의 색, fill은 막대·박스의 채우기 색입니다. 같은 이름의 속성을 매핑했다면 같은 계열 함수를 씁니다.

scale_color_manual — 색상 직접 지정

library(tidyverse)

ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
  geom_point(size = 2) +
  scale_color_manual(
    values = c("4" = "#E63946", "f" = "#457B9D", "r" = "#2A9D8F"),
    labels = c("4" = "사륜구동", "f" = "전륜구동", "r" = "후륜구동")
  ) +
  labs(
    title = "구동 방식별 배기량과 연비",
    x     = "엔진 배기량 (리터)",
    y     = "고속도로 연비 (mpg)",
    color = "구동 방식"
  ) +
  theme_minimal()

values에 각 범주에 해당하는 색상 코드를 지정합니다. labels로 범례에 표시되는 이름을 바꿉니다. 16진수 색상 코드를 직접 입력하면 어떤 색이든 쓸 수 있습니다.

fill에 적용하려면 scale_fill_manual()을 씁니다.

ggplot(mpg, aes(x = class, fill = drv)) +
  geom_bar(position = "fill") +
  scale_fill_manual(
    values = c("4" = "#E63946", "f" = "#457B9D", "r" = "#2A9D8F"),
    labels = c("4" = "사륜구동", "f" = "전륜구동", "r" = "후륜구동")
  ) +
  labs(
    title = "클래스별 구동 방식 비율",
    x     = "클래스",
    y     = "비율",
    fill  = "구동 방식"
  ) +
  theme_minimal()

scale_color_brewer — 검증된 팔레트 사용

색상 이론에 기반한 팔레트를 쓰고 싶을 때는 ColorBrewer 팔레트를 활용합니다. 지도 시각화에서 출발한 팔레트이지만 일반 차트에서도 널리 쓰입니다.

ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
  geom_point(size = 2, alpha = 0.8) +
  scale_color_brewer(palette = "Set2") +
  labs(
    title = "클래스별 배기량과 연비",
    x     = "배기량 (리터)",
    y     = "고속도로 연비 (mpg)",
    color = "클래스"
  ) +
  theme_minimal()

자주 쓰이는 팔레트를 정리합니다.

질적(Qualitative) 팔레트 — 범주형 변수에 사용.

팔레트 특징
Set1 선명하고 구분이 뚜렷함
Set2 부드럽고 자연스러운 색조
Set3 밝고 파스텔 톤
Dark2 어둡고 진한 색조
Paired 쌍으로 연결된 색상

순차(Sequential) 팔레트 — 낮은 값에서 높은 값으로 이어지는 연속형 변수에 사용.

팔레트 색상 범위
Blues 밝은 파란 → 진한 파란
Greens 밝은 녹색 → 진한 녹색
YlOrRd 노랑 → 주황 → 빨강

발산(Diverging) 팔레트 — 중간값을 기준으로 양방향으로 퍼지는 변수에 사용.

팔레트 색상
RdBu 빨강 ← 중간 → 파랑
PiYG 분홍 ← 중간 → 초록
# 가능한 팔레트 목록 확인
RColorBrewer::display.brewer.all()

scale_fill_gradient — 연속형 변수에 색상 그라디언트

연속형 변수를 색상으로 표현할 때는 scale_fill_gradient() 또는 scale_color_gradient()를 씁니다.

ggplot(diamonds, aes(x = carat, y = price, color = depth)) +
  geom_point(alpha = 0.3, size = 0.8) +
  scale_color_gradient(low = "#AED6F1", high = "#1A5276") +
  labs(
    title = "다이아몬드 캐럿, 가격, 깊이 관계",
    x     = "캐럿",
    y     = "가격 (달러)",
    color = "깊이 (%)"
  ) +
  theme_minimal()

lowhigh에 각각 낮은 값과 높은 값의 색상을 지정합니다.

세 가지 색으로 그라디언트를 만들려면 scale_color_gradient2()를 씁니다.

scale_color_gradient2(
  low  = "blue",
  mid  = "white",
  high = "red",
  midpoint = 60   # 중간값 기준점
)

기본 테마 함수

테마는 차트의 배경, 그리드, 글자, 테두리 같은 비데이터 요소의 스타일을 결정합니다. ggplot2에는 여러 완성된 테마가 내장되어 있습니다.

p <- ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
  geom_point(size = 2) +
  labs(title = "테마 비교", x = "배기량", y = "연비")

p + theme_gray()     # 기본 테마 (회색 배경)
p + theme_bw()       # 흑백 (흰 배경 + 테두리)
p + theme_minimal()  # 깔끔 (최소한의 요소)
p + theme_classic()  # 고전 (흰 배경, 축선만)
p + theme_light()    # 밝은 배경, 연한 그리드
p + theme_dark()     # 어두운 배경
p + theme_void()     # 아무것도 없음 (지도 등에 사용)

보고서나 논문에는 theme_classic()이나 theme_bw()가 깔끔합니다. 프레젠테이션에는 theme_minimal()이 세련되어 보입니다.

theme()으로 세부 조정

theme_minimal() 같은 완성 테마를 적용한 뒤에도 세부 요소를 추가로 조정할 수 있습니다.

ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
  geom_point(size = 2, alpha = 0.8) +
  labs(
    title    = "배기량과 고속도로 연비",
    subtitle = "차량 클래스별 색상 구분",
    x        = "엔진 배기량 (리터)",
    y        = "고속도로 연비 (mpg)",
    color    = "클래스"
  ) +
  theme_minimal() +
  theme(
    plot.title      = element_text(size = 16, face = "bold"),
    plot.subtitle   = element_text(size = 11, color = "gray40"),
    axis.title      = element_text(size = 11),
    axis.text       = element_text(size = 9),
    legend.position = "bottom",
    legend.title    = element_text(face = "bold"),
    panel.grid.minor = element_blank()
  )

자주 쓰는 theme() 인수를 정리합니다.

인수 역할
plot.title 제목 스타일
plot.subtitle 부제목 스타일
axis.title 축 제목 스타일
axis.text 축 눈금 레이블 스타일
axis.text.x X축 눈금 레이블만
legend.position 범례 위치 ("right", "bottom", "top", "none")
legend.title 범례 제목 스타일
panel.grid.major 주 그리드선
panel.grid.minor 보조 그리드선
panel.background 플롯 배경
plot.background 전체 배경

element_text()는 텍스트 요소를, element_blank()는 요소를 완전히 제거할 때 씁니다.

X축 레이블 회전

범주 이름이 길면 X축 레이블이 겹칩니다.

ggplot(mpg, aes(x = class)) +
  geom_bar(fill = "steelblue") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1)
  ) +
  labs(title = "클래스별 대수", x = "클래스", y = "대수")

angle = 45로 45도 기울이고, hjust = 1로 오른쪽 정렬해 레이블과 눈금 위치를 맞춥니다.

나만의 테마 만들기

같은 스타일을 여러 차트에 반복 적용할 때는 커스텀 테마 함수를 만들면 편합니다.

# 커스텀 테마 정의
theme_report <- function() {
  theme_minimal() +
    theme(
      plot.title       = element_text(size = 14, face = "bold", margin = margin(b = 8)),
      plot.subtitle    = element_text(size = 10, color = "gray50", margin = margin(b = 12)),
      axis.title       = element_text(size = 10, color = "gray30"),
      axis.text        = element_text(size = 9, color = "gray50"),
      panel.grid.minor = element_blank(),
      panel.grid.major = element_line(color = "gray90"),
      legend.position  = "bottom",
      legend.key.size  = unit(0.4, "cm")
    )
}

# 적용
ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
  geom_point(size = 2, alpha = 0.8) +
  labs(
    title    = "배기량과 고속도로 연비",
    subtitle = "차량 클래스별",
    x        = "배기량 (리터)",
    y        = "고속도로 연비 (mpg)",
    color    = "클래스"
  ) +
  theme_report()

theme_report()를 정의해두면 모든 차트에 + theme_report()만 붙이면 됩니다.

색상과 테마는 데이터를 바꾸지 않습니다. 하지만 같은 데이터라도 어떻게 표현하느냐에 따라 독자가 받는 인상이 크게 달라집니다. 다음 챕터에서는 facet으로 여러 패널을 만들어 그룹 비교를 더욱 효과적으로 하는 방법을 살펴봅니다.