iBetter Books
수정

Ch 01. ggplot2의 레이어 개념

차트를 만드는 방법은 두 가지가 있습니다. 하나는 "이 데이터로 막대그래프 그려줘"라고 명령하는 방식이고, 다른 하나는 "이 데이터를 X축에 놓고, 저 데이터를 Y축에 놓고, 막대 모양으로 표현하고, 색은 이렇게 해줘"라고 쌓아 올리는 방식입니다.

ggplot2는 후자입니다. 차트를 레이어(layer)의 조합으로 봅니다. 이 철학을 이해하면 어떤 복잡한 차트도 만들 수 있습니다.

Grammar of Graphics란

ggplot2는 Leland Wilkinson의 책 "The Grammar of Graphics"에서 영감을 받아 Hadley Wickham이 만들었습니다. 문법(grammar)이라는 단어가 핵심입니다. 언어에 문법이 있듯이, 시각화에도 규칙이 있다는 생각입니다.

이 문법은 차트를 몇 가지 구성 요소로 분해합니다.

구성 요소 역할 예시
data 사용할 데이터 mpg, iris
aes() 미적 속성 매핑 x, y, color, size
geom 기하학적 표현 점, 선, 막대
stat 통계 변환 count, mean, density
coord 좌표 시스템 직교, 극좌표
facet 패널 분할 그룹별 소 차트
theme 시각적 스타일 글자 크기, 배경색

이 요소들을 + 연산자로 차례로 더해가며 차트를 만듭니다. 레이어를 쌓는 것입니다.

첫 번째 ggplot2 차트

ggplot2는 tidyverse에 포함되어 있습니다.

library(tidyverse)

# mpg 데이터셋 확인
glimpse(mpg)
Rows: 234
Columns: 11
$ manufacturer <chr> "audi", "audi", "audi", "audi", "audi", "audi", "audi", …
$ model        <chr> "a4", "a4", "a4", "a4", "a4", "a4", "a4", "a4 quattro",…
$ displ        <dbl> 1.8, 1.8, 2.0, 2.0, 2.8, 2.8, 3.1, 1.8, 1.8, 2.0, 2.0,…
$ year         <int> 1999, 1999, 2008, 2008, 1999, 1999, 2008, 1999, 1999, 20…
$ cyl          <int> 4, 4, 4, 4, 6, 6, 6, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 8, …
$ trans        <chr> "auto(l5)", "manual(m5)", "manual(m6)", "auto(av)", "aut…
$ drv          <chr> "f", "f", "f", "f", "f", "f", "f", "4", "4", "4", "4",…
$ cty          <int> 18, 21, 20, 21, 16, 18, 18, 18, 16, 20, 19, 15, 17, 17,…
$ hwy          <int> 29, 29, 31, 30, 26, 26, 27, 26, 25, 28, 27, 25, 25, 25,…
$ fl           <chr> "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p",…
$ class        <chr> "compact", "compact", "compact", "compact", "compact", "…

mpg는 1999~2008년 자동차 연비 데이터입니다. displ은 엔진 배기량, hwy는 고속도로 연비입니다. 배기량이 클수록 연비가 나쁠까요? 산점도로 확인해봅니다.

ggplot(data = mpg, aes(x = displ, y = hwy)) +
  geom_point()

세 줄짜리 코드로 차트가 만들어집니다. 하나씩 뜯어봅니다.

  • ggplot(data = mpg) — mpg 데이터를 사용한다고 선언합니다. 아직 아무것도 그리지 않습니다. 빈 캔버스입니다.
  • aes(x = displ, y = hwy) — X축에 displ, Y축에 hwy를 매핑합니다. "이 변수를 저 위치에 표현하겠다"는 약속입니다.
  • + geom_point() — 점(point) 모양으로 그립니다.

배기량이 커질수록 연비가 낮아지는 경향이 보입니다. 예상과 맞습니다.

aes() — 미적 속성 매핑

aes()는 aesthetic의 약자입니다. 데이터의 변수를 차트의 시각적 속성에 연결하는 역할을 합니다.

x, y 외에도 다양한 속성을 매핑할 수 있습니다.

ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
  geom_point()

color = class를 추가하면 차량 클래스별로 색이 달라집니다. 범례도 자동으로 생성됩니다. SUV 계열이 배기량이 크고 연비가 낮은 오른쪽 아래에 몰려 있습니다.

크기도 변수에 연결할 수 있습니다.

ggplot(mpg, aes(x = displ, y = hwy, color = class, size = cyl)) +
  geom_point(alpha = 0.6)

alpha = 0.6은 투명도를 60%로 설정합니다. 점이 겹쳐도 아래 점이 보입니다. alphaaes() 안이 아니라 geom_point() 안에 넣었습니다. 데이터 변수가 아니라 고정값이기 때문입니다.

aes() 안 vs 밖의 차이를 꼭 기억합니다.

# 데이터 변수에 따라 색 결정 — aes() 안
aes(color = class)

# 모든 점을 파란색으로 고정 — aes() 밖
geom_point(color = "blue")

geom — 기하학적 표현

geom_*() 함수는 데이터를 어떤 모양으로 그릴지 결정합니다. 자주 쓰는 geom을 정리합니다.

함수 용도
geom_point() 산점도
geom_line() 꺾은선 그래프
geom_bar() 빈도 막대 (자동 집계)
geom_col() 값 막대 (직접 지정)
geom_histogram() 히스토그램
geom_boxplot() 박스플롯
geom_violin() 바이올린 플롯
geom_density() 밀도 그래프
geom_smooth() 추세선
geom_text() 텍스트 레이블

하나의 차트에 여러 geom을 함께 쓸 수 있습니다.

ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point(color = "steelblue", alpha = 0.5) +
  geom_smooth(method = "lm", se = TRUE)

산점도 위에 선형 회귀 추세선과 신뢰 구간(se)이 덧그려집니다. method = "lm"은 선형 모델(linear model)을 뜻합니다.

stat — 통계 변환

geom 뒤에서 조용히 작동하는 것이 stat입니다. 예를 들어 geom_bar()는 기본적으로 stat = "count"를 사용합니다. 데이터를 받아 빈도를 계산한 다음 막대를 그립니다.

ggplot(mpg, aes(x = class)) +
  geom_bar()

mpg 데이터에 클래스별 빈도를 계산하는 코드가 없지만, geom_bar가 알아서 셉니다. 이것이 stat의 역할입니다.

직접 계산한 값을 막대로 그리려면 stat = "identity"를 쓰거나, geom_col()을 사용합니다.

coord — 좌표 시스템

기본은 데카르트 좌표계(coord_cartesian)입니다. 필요에 따라 바꿀 수 있습니다.

# 가로 막대그래프 — 축 뒤집기
ggplot(mpg, aes(x = class)) +
  geom_bar() +
  coord_flip()

coord_flip()은 X축과 Y축을 맞바꿉니다. 세로 막대그래프가 가로 막대그래프로 바뀝니다. 클래스 이름이 Y축에 표시되어 읽기 편해집니다.

facet — 패널 분할

데이터를 그룹별로 나누어 소 차트를 만듭니다. 비교 시각화에 강력합니다. 자세한 내용은 Ch 05에서 다룹니다.

ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point() +
  facet_wrap(~ class)

차량 클래스별로 별도 패널이 생성됩니다. 각 그룹의 분포를 한눈에 비교할 수 있습니다.

theme — 시각적 스타일

theme_*()으로 차트의 전체 스타일을 한 번에 바꿉니다.

ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point(color = "steelblue") +
  theme_minimal()

자주 쓰는 테마는 다음과 같습니다.

테마 함수 느낌
theme_gray() 기본 (회색 배경)
theme_bw() 흑백, 그리드 있음
theme_minimal() 깔끔, 그리드 최소
theme_classic() 고전적, 테두리선
theme_void() 배경 없음

레이어를 쌓는 전체 구조

ggplot2 차트의 기본 틀을 정리합니다.

ggplot(data = <데이터>, aes(<매핑>)) +   # 캔버스와 매핑
  geom_<함수>(<옵션>) +                   # 무엇을 그릴까
  scale_<속성>_<유형>(<옵션>) +           # 스케일 조정
  coord_<함수>() +                        # 좌표계
  facet_<함수>(<공식>) +                  # 패널 분할
  labs(title = "", x = "", y = "") +      # 제목과 축 이름
  theme_<함수>()                          # 스타일

모두 필요한 것은 아닙니다. data와 aes, geom만 있어도 차트가 만들어집니다. 나머지는 차트를 더 잘 표현하고 싶을 때 덧붙입니다.

labs()로 제목과 축 이름 붙이기

완성도 있는 차트에는 제목과 축 설명이 있어야 합니다.

ggplot(mpg, aes(x = displ, y = hwy, color = class)) +
  geom_point(alpha = 0.7) +
  labs(
    title    = "배기량과 고속도로 연비의 관계",
    subtitle = "차량 클래스별 색상 구분",
    x        = "엔진 배기량 (리터)",
    y        = "고속도로 연비 (mpg)",
    color    = "차량 클래스",
    caption  = "출처: ggplot2 내장 데이터 mpg"
  ) +
  theme_minimal()

title은 상단 제목, subtitle은 부제목, caption은 하단 각주입니다. color = "차량 클래스"는 범례 제목을 바꿉니다.

이렇게 레이어를 하나씩 쌓아가는 방식이 ggplot2의 핵심입니다. 처음에는 geom 하나로 시작하고, 필요할 때 레이어를 추가합니다. 다음 챕터부터 각 geom을 구체적으로 살펴봅니다.