5.4 ggplot2

Prerequisites: tidyverse 패키지 또는 ggplot2 패키지 읽어오기: require(tidyverse) 또는 require(ggplot2) 실행
  • 데이터에 대한 그래프는 데이터의 속성(수치형, 범주형)과 시각적 속성(점, x-y 좌표 위치, 선, 색상, 막대의 높이) 간에 대응 또는 매핑(mapping) 으로 이루어짐
  • R 에서 가장 유명한 데이터 시각화 패키지 중 하나로 2005년 Hadley Wickham이 개발 및 배포
  • Leland Wilkinson 의 grammar of graphics (Wilkinson 2012) 를 구현
Grammar of graphics: 그래프를 구현하기 위한 일관적인 체계로 그래프를 데이터, 스케일, 레이어, 좌표 등과 같은 의미론적 요소(sementic components) 로 나눔
  • ggplot의 grammar of graphics
ggplot의 grammar of graphics 주요 구성 요소

Figure 5.19: ggplot의 grammar of graphics 주요 구성 요소

  • R 기본 graphics 패키지의 경우 데이터 속성을 시각적 속성으로 매핑 시 매 경우가 고유한 작업이고, 매핑이 변경될 경우 데이터를 재구성하거나 완전히 다른 plotting 함수를 적용해야 함.
  • R base graphics와 ggplot의 비교
`summarise()` regrouping output by 'supp' (override with `.groups` argument)
R 기본 barplot() 생성 그래프

Figure 5.20: R 기본 barplot() 생성 그래프

  • dose 별 OJ와 VC 막대도표: dose로 그룹화를 하기 위해 데이터 구조 변경(전치) 필요
R 기본 barplot() 생성 그래프: 데이터 전치

Figure 5.21: R 기본 barplot() 생성 그래프: 데이터 전치

  • 막대 대신 선(line)으로 표현
R 기본 선 그래프: plot(), lines() 함수 사용

Figure 5.22: R 기본 선 그래프: plot(), lines() 함수 사용

  • plot() 함수 호출 시 y 축 범위가 첫 번째 선에 대해서만 설정
  • x 축이 범주 대신 번호가 사용
  • ggplot 사용: 데이터 프레임에만 적용 가능(데이터 구조는 long-format)
ggplot()과 geom_bar()을 이용한 막대 도표

Figure 5.23: ggplot()과 geom_bar()을 이용한 막대 도표

  • 데이터 구조를 변경하지 않고 ggplot의 매핑 변수 변경
x와 fill의 mapping 변경

Figure 5.24: x와 fill의 mapping 변경

  • ggplot을 이용한 선 도표 생성
geom_line()을 이용한 선 그래프 생성

Figure 5.25: geom_line()을 이용한 선 그래프 생성

  • 기본 그래프 함수를 이용해 막대도표 대신 선 도표 생성 시 완전히 다른 명령 사용
  • 선 그래프 생성 시 기본 그래프는 하나씩 도표를 추가한 반면, geom_line()의 경우 모든 선이 한번에 그려짐

5.4.1 기본 문법

용어(terminology)

  • data: 시각화의 대상으로 관측값과 변수(열)로 이루어짐
  • geom: 데이터의 값을 시각적으로 보여주기 위한 레이어로 막대, 선, 점과 같은 기하학적 객체
  • aesthetic: geom의 시각적 속성을 정의하며, x, y 위치, 선 색상, 점 모양 등을 정의
  • mapping: 데이터 값을 asthetic에 매핑
  • scale: asthetic에 매핑 시 세부 값들을 제어
  • guide: 그래프 해석에 도움을 주는 속성으로 x-y 축의 눈금, 레이블, 범례(legend)를 포함
  • annotation: 생성한 그래프 위에 추가적인 정보(선, 화살표, 텍스트, 도형 등) 추가
  • theme: 그래프의 비데이터적 요소(제목, 레이블, 글꼴, 배경색, 격자, 범례 등) 제어를 통해 그래프의 미적 효과 극대화

ggplot 계열 함수에서 범주형 변수(categorical variable)은 이산형(discrete), 수치형 변수(numeric variable)을 연속형(continuous)이라고 명칭함.

ggplot 그래프 생성 기본 단계(각 단계(layer)는 + 연산자로 덧붙혀짐)

  1. ggplot()으로 ggplot 객체 초기화
  2. aes() 함수로 x-y 축 지정
  3. geom 계열 함수로 데이터를 시각적 요소로 매핑. 이때 aes() 함수와 같이 색상, 크기 등 지정
  4. scale 계열 함수를 이용해 asthetic의 세부 값을 조정
  5. 축 제목, 레이블, 범례 설정 조정
  6. 필요 시 theme 조정을 통해 시각적 요소 가미
  • ggplot(): ggplot 객체를 생성하는 함수로 시각화할 데이터가 무엇인지, 그리고 데이터에 포함된 변수들이 어떤 asthetic에 매핑되는지를 선언
  • aes(): 데이터 내 변수들이 어떤 geoms 레이어에서 어떤 시각적 속성을 갖는지를 지정해주는 함수로 ggplot() 함수 내, 혹은 독립적인 레이어로 추가 가능
    • ggplot에서 지정한 데이터 내에서 평가되기 때문에 변수명 지정 시 원래 데이터셋 참조할 필요 없음(예: ggplot(data = car, aes(x = speed)))
  • 주요 aesthetics
    • x, y: x-y 축에 해당하는 변수명. xy의 이름은 생략 가능(예: ggplot(data = car, aes(speed, dist)로도 사용 가능))
    • color: 점, 선, 텍스트 색상
    • fill: 면(막대, 상자, 도형 등) 색상
    • alpha: 색상의 투명도
    • group: 시각화에 사용할 데이터의 그룹
    • size: 점, 선, 텍스트의 크기 또는 굵기
    • shape: 점의 모양(그림 5.3 참고). R 기본 그래픽 파라미터 pch와 호환
    • linetype: 선의 형태 지정하며 그림 5.3 의 선 형태 지정 방법 준용(숫자, 문자열 모두 사용 가능)
  • 색상 관련 aesthetics: color, fill, alpha
    • aes() 함수 내부 또는 외부에서 인수 조정 가능(함수 내부: 변수명으로 지정, 함수 외부: 특정 값으로 지정)

  • 그룹(group) aesthetic
    • 기본적으로 aes() 내부에서 aesthetic에 대응하는 변수가 이산형(범주형) 변수로 정해짐
    • 보통은 color, shape, linetype 으로 그룹 지정이 가능하지만 충분하지 않은 경우 group 인수 값 지정

  • 크기(size), 점 모양(shape), 선모양(linetype) aesthetic

5.4.2 Geoms: 선 관련 geometric

  • geom_line(): x축에 대응한 변수의 순서대로 관측값을 선으로 연결
  • geom_path(): 관측치가 데이터셋에 나타난 순서대로 선으로 연결
  • geom_abline(slope, intercept): 기울기(slope) 절편(intercept)에 대한 직선 \(\rightarrow\) R 기본 그래픽 함수 abline(a=value, b=value)와 유사
  • geom_vline(xintercept): x축에 수직(y 축에 수평)인 직선 생성
  • geom_hline(yintecept): x축에 수평(y 축에 수직)인 직선 생성

5.4.4 Geoms: 막대 geometrics

  • geom_bar(): 범주형(factor 또는 문자열) 변수에 대응하는 케이스의 수를 막대의 높이로 나타냄.
    • 기본적으로 stat_count()를 통해 각 집단 별 케이스 수가 그래프에 표현
    • 함수 내 stat 인수 값을 “identity”로 설정 시 데이터 값 표현 가능
  • geom_col(): 데이터 값 자체를 높이로 표현
    • stat_identity()를 사용

Examples

`summarise()` ungrouping output (override with `.groups` argument)

  • 막대도표 값 순으로 정렬하기
`summarise()` ungrouping output (override with `.groups` argument)

5.4.5 Geom: 수직 범위선 관련 geometrics

오차 막대, 신뢰구간 등을 도식화 할 때 많이 활용되며 데이터의 변수를 mapping 시 위치 관련 aesthetic에 x, y 외에 ymin(또는 xmin), ymax(또는 xmax)가 사용

  • geom_errorbar(): 주어진 범위(구간) 내 오차막대(errorbar) 생성 \(\rightarrow\) 오차막대는 선 끝에 범위 선과 수직인 선이 생성
  • geom_linerange(): 주어진 범위(구간) 내 선 생성
`summarise()` regrouping output by 'cut' (override with `.groups` argument)

  • 평균-95 % 신뢰구간 오차 막대 도표 예시

  • 막대도표 위에 오차 막대 표시 예제
`summarise()` regrouping output by 'wool' (override with `.groups` argument)

  • 95 % 신뢰구간 시뮬레이션 예제

5.4.6 Geoms: 텍스트 관련 geometrics

x-y 좌표축에 텍스트를 추가하기 위한 함수. 여기서 미리 지정된 x-y aesthetic에 대한 매핑은 사용할 수 있으며, 별도의 aesthetic 정의를 통해 새로운 좌표점에 텍스트 추가 가능

  • geom_text()
  • geom_label(): 추가한 텍스트 뒤에 사각형을 동시에 출력
  • geom_text() 예시

ggplot 텍스트 위치 조정

R 기본 그래픽 함수 text() 함수의 adj 인수와 유사

  • vjust: (-) 방향 \(\uparrow\); middle = 0.5; (+) 방향 \(\downarrow\)
  • hjust: (-) 방향 \(\rightarrow\); middle = 0.5; (+) 방향 \(\leftarrow\)

vjust, hjust 모두 (0, 1) 밖의 값을 갖을 수 있으나, 이러한 위치 조정은 그래프의 크기에 상대적이기 때문에 해당 값들을 이용해 텍스트 위치를 과도하게 조정하는 것이 바람직한 방법은 아님.

hjust와 vjust 값에 따른 텍스트 위치. https://ggplot2.tidyverse.org/articles/ggplot2-specs.html 인용

Figure 5.26: hjust와 vjust 값에 따른 텍스트 위치. https://ggplot2.tidyverse.org/articles/ggplot2-specs.html 인용

geom_text() 수식(math) 표기

  • R 기본 그래픽 함수에서 적용한 expression(), bquote() 함수를 이용해 수식 표현 가능.
  • bquote()를 이용 시 생성한 표현을 다시 parsing (문자열을 expression 구문으로 해석) 하기 위해 deparse() 함수를 통해 문자열로 변환해줘야 함. 이 때 텍스트가 label의 값으로 입력이 되기 때문에 텍스트를 expression() 형태로 바꿔주기 위해 parse = TRUE 로 설정해야 수식 표현 가능

5.4.8 Geoms: 통계 그래프 관련 geometrics

다음 소개하는 그래프 함수는 기본적으로 stat_* 함수로 도출한 통계량을 바탕으로 그래프 생성

-geom_histogram(): stat_bin() (연속형 변수)를 사용한 히스토그램 생성

geom_histogram 예시

  • 히스토그램 인수 조정
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

  • 다중 집단 히스토그램

-geom_density(): 막대 형태의 히스토그램을 부드러운(smoothed) 선(여기서 y 값은 밀도임)으로 나타낸 곡선으로, 커널 밀도 추정(kernel density estimate)을 통해 밀도 곡선 추정

-geom_boxplot(): R 기본 그래픽스 함수 boxplot()과 유사. stat_boxplot() 함수의 결과값을 기반으로 그래프 도출

  • geom_boxplot() + geom_jitter() 콜라보레이션

-geom_smooth(): x-y 관계에 대한 패턴을 도식화하기 위한 그래프로 아래와 같은 방법(method)을 이용해 추세선과 추정 직선의 오차 그래프 출력

  • 선형 회귀 곡선(linear model, lm)
    • 일반화 선형 모형(generalized linear model, glm)
    • 국소 다항 회귀 곡선(locally estimated scatterplot smoothing, loess)
    • generalized addictive model (GAM, gam)
`geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
`geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
`geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'
`geom_smooth()` using formula 'y ~ x'

5.4.9 Scales: x-y 축 관련 aesthetic 조정

  • scale_x_*, scale_y_*: x-y 축의 범위, plot 상 눈금선, 축 제목 등을 조정
    • xlim(), ylim(): scale_x_*, scale_y_*의 특별한 케이스로 x-y 축의 범위 조정

5.4.10 Scales: 색상 관련 aesthetic 조정

  • scale_color_*, scale_fill_*: aes()에 color 또는 fill이 정의된 경우, 기본 색상 변경 가능
  • 색상 조정은 palette를 통해 가능하며, 색상 파레트를 사용할 경우 scale_*_brewer()를 통해 palette 설정 가능
  • RColorBrewer 패키지 설치 시 보다 다양한 palette 사용 가능

5.4.11 Scales: 크기, 선 종류, 점 모양 aesthetic 조정

  • scale_size_*: size에 대한 세부적인 값 지정 가능
  • scale_shape_*: shape가 aes() 함수에 사용된 경우, shape에 대한 세부 값(점 모양, 크기, 색 등 지정 가능)
  • scale_linetype_*: linetype이 aes() 함수에 사용된 경우, linetype에 대한 세부 값(선 종류, 굵기 등 조정 가능)

5.4.13 Guides: x-y 축 및 그래프 제목 관련

  • labs(): x-y 축 제목, 부제목, 캡션 조정
    • xlab(), ylab(), ggtitle(): labs()의 조정 인수를 개별 함수로 구현
  • guide_legend(): guides() 함수 내부에서 사용되며, 범례 영역 조정하기 위한 함수
    • 이미 정의한 aesthetic에 대한 범례 영역의 세부 속성을 변경하고 싶은 경우 overrride.aes 인수 조정(입력값은 리스트)
Parsed with column specification:
cols(
  iso = col_character(),
  country = col_character(),
  region = col_character(),
  year = col_double(),
  population = col_double(),
  life_expectancy = col_double(),
  gdp_cap = col_double()
)

5.4.14 Facets: 국소 시각화 기법

  • facet_grid(): 행과 열에 대한 facet (면 또는 패널)을 정의한 변수에 의해 패널 행렬을 구성한 그래프로 두 개 이상의 범주형(이산) 변수가 있고 변수의 모든 조합이 데이터에 존제하는 경우 유용
  • facet_wrap(): 1차원 패널을 2차원으로 변환. 일반적으로 facet_grid() 보다 화면 분할이 효율적이고, 서로 다른 단위로 측정된 변수를 패널 형태로 출력하고자 할 때 데이터를 long format으로 변환 후 적용

  • cyl을 행, class를 열로 사용하여 cylclass의 수준 조합 별 산점도 출력

  • facet_wrap()을 이용한 다변수 패널 도표
Rows: 2,870
Columns: 4
$ date     <date> 1967-07-01, 1967-08-01, 1967-09-01, 1967-10-01, 1967-11-0...
$ variable <chr> "pce", "pce", "pce", "pce", "pce", "pce", "pce", "pce", "p...
$ value    <dbl> 506.7, 509.8, 515.6, 512.2, 517.4, 525.1, 530.9, 533.6, 54...
$ value01  <dbl> 0.0000000000, 0.0002652497, 0.0007615234, 0.0004706043, 0....

두 개 이상의 ggplot 객체를 한 화면에 출력하고자 할 때(R 기본 그래픽스에서 par(mfrow = c(n, m))와 유사하게), 별도의 패키지(예: gridExtra, ggpubr, cowplot 패키지 등)가 요구됨. 이 중 가장 사용하기 용이한 패키지와 함수는 ggubr::ggarrange() 임.

5.4.15 Themes

  • theme(): ggplot의 결과에서 비데이터(non-data)적 요소(예: 제목, 레이블, 글꼴, 배경, 눈금선, 범례)를 조정하기 위한 함수로 출력 그래프의 전반적인 형태를 정의함.
  • theme()을 이용한 비데이터적 요소는 다음의 4 가지 속성을 가짐
    • line: 모든 선 구성 요소(x-y 축선, 눈금선, 보조선 등) \(\rightarrow\) element_line()
    • rect: 모든 사각형 구성 요소(facet strips, 범례, 배경 등) \(\rightarrow\) element_rect()
    • text: 모든 텍스트 구성 요소(눈금선 레이블, 범례 표시 텍스트, …) \(\rightarrow\) element_text()
    • title: 모든 제목 요소(plot, 축, 범례 등) \(\rightarrow\) element_text()
  • element_blank(): 특정 요소를 없앨 때 사용

<element_text()>

  • axis.title: ggplot에 표현된 모든 축의 제목 조정(크기, 폰트 등)
    • axis.title.x, axis.title.y: x, y 축 각각의 제목 조정
  • axis.text: 모든 축의 눈금 레이블 크기 폰트 등 조정
    • axis.text.x, axis.text.y: x, y 축 각각의 눈금선 레이블 조정
  • legend.text: 범례표시의 텍스트 조정
  • legend.title: 범례 제목 조정
  • plot.title, plot.subtitle, plot.caption: ggplot 제목, 부제목, 캡션 텍스트 조정
  • strip.text: facet 레이블 텍스트 조정
    • strip.text.x, strip.text.y

<element_line()>: 선과 관련된 모든 요소 조정

  • axis.ticks: 모든 눈금선 조정
    • axis.ticks.x, axis.ticks.y: x, y 축 각각의 눈금선 조정
  • axis.line: 모든 axis 선 설정 조정
    • axis.line.x, axis.line.y:
  • panel.grid: plot 내 주(major) 또는 보조(minor) 격자선 조정
    • panel.grid.minor, panel.grid.minor.x, panel.grid.minor.y
    • panel.grid.major, panel.grid.major.x, panel.grid.major.y

<element_rect()>: plot 배경 및 범례 배경 및 표시 상자 설정

기타

  • legend.position: 범례 위치 조정
    • “none”, “left”, “right”, “bottom”, “top” 과 같은 문자열 값 또는 좌표의 상대적 위치(0에서 1사이 값)을 나타내는 2차원 벡터 값을 가짐
  • legend.direction: 범례 표시 방향 설정
    • “horizontal” (수평) 또는 “vertical” (수직)

theme() 함수를 이용한 그래프 조정 옵션은 help(theme) 또는 ggplot2 공식 메뉴얼 또는 Statistical tools for high-throughput data analysis를 참고

가능한 완성 theme

  • ggplot2 패키지 제공 theme
    • theme_grey()
    • theme_bw()
    • theme_light()
    • theme_minimal()
    • theme_classic()

**ggplot 관련 알아두면 유용한 팁

  • ggplot2는 ggplot2에 포함된 모든 함수에 대한 메뉴얼을 제공
  • r-statistics.co에서 ggplot 예시 확인 가능
  • ggplot2 패키지에서 제공하는 기본 theme 외에 ggtheme, ggpubr 과 같은 패키지를 통해 보다 다양한 theme을 적용할 수 있음

5.4.16 확장 예제

  • Our World in Data에서 각 국가별 코로나 19 바이러스 통계 데이터 제공
  • 감염자 및 사망자 수 통계는 하루 단위로 업데이트가 되고 있고, 각 국가별 검사 수는 일주일 단위로 업데이트

데이터 전처리

  • 데이터 불러오기: covid19-cases-20200601.txt, country_pubhealth.csv, country_info.txt
Parsed with column specification:
cols(
  iso_code = col_character(),
  date = col_date(format = ""),
  total_cases = col_double(),
  new_cases = col_double(),
  total_deaths = col_double(),
  new_deaths = col_double(),
  total_tests = col_double(),
  new_tests = col_double(),
  new_tests_smoothed = col_double()
)
Parsed with column specification:
cols(
  location = col_character(),
  cvd_death_rate = col_double(),
  diabetes_prevalence = col_double(),
  female_smokers = col_double(),
  male_smokers = col_double(),
  handwashing_facilities = col_double(),
  hospital_beds_per_100k = col_double()
)

데이터 코드북

데이터 전처리

  1. Filtering
    • covid19 에서 iso_code가 “OWID_WRL”인 케이스 제외
    • 2020년 3월 1일 부터 2020년 5월 31 일 까지 데이터만 추출
  1. Join: covid19를 기준으로 나머지 두 데이터셋(country, country_pubhealth) 결합
  1. 대륙(continent) 변수 생성(region 변수를 활용해서)
  1. 케이스, 사망자 수 관련 변수를 이용해 100만명 당 확진자 수 및 사망자 수 계산(변수이름은 기존 변수명 마지막에 "_per_million"을 추가)
  1. 2020년 5월 31일 기준 총 확진자 수가 2000 명 이상인 국가만 추출
  1. 각 국가별 total_test 결측값 대체
    • 최초 시점의 total_test가 결측인 경우 0으로 대체
    • 기록 중 중간에 결측이 발생한 경우 이전 시점 값으로 대체
  1. "_tests“가 포함된 변수들에 대해 인구 천 명당 검사 수 계산(변수이름은 기존 변수명 마지막에”_per_thousand"을 추가)
  1. iso_code, date, location, continent, population, 그리고 “case”, “deaths”, “tests”가 포함된 변수 선택
Rows: 9,733
Columns: 19
$ iso_code                        <chr> "AFG", "AFG", "AFG", "AFG", "AFG", ...
$ date                            <date> 2020-03-01, 2020-03-02, 2020-03-08...
$ location                        <chr> "Afghanistan", "Afghanistan", "Afgh...
$ continent                       <fct> Asia, Asia, Asia, Asia, Asia, Asia,...
$ population                      <dbl> 38928341, 38928341, 38928341, 38928...
$ total_cases                     <dbl> 1, 1, 4, 7, 10, 16, 21, 22, 22, 22,...
$ new_cases                       <dbl> 0, 0, 3, 3, 3, 6, 5, 1, 0, 0, 2, 0,...
$ total_deaths                    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ new_deaths                      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ total_tests                     <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ new_tests                       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA,...
$ new_tests_smoothed              <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA,...
$ total_cases_per_million         <dbl> 0.02568823, 0.02568823, 0.10275290,...
$ new_cases_per_million           <dbl> 0.00000000, 0.00000000, 0.07706468,...
$ total_deaths_per_million        <dbl> 0.00000000, 0.00000000, 0.00000000,...
$ new_deaths_per_million          <dbl> 0.00000000, 0.00000000, 0.00000000,...
$ total_tests_per_thousand        <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ new_tests_per_thousand          <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA,...
$ new_tests_smoothed_per_thousand <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA,...

시각화

  1. 대륙별 일별 일일 확진자 수(new_case 기준)에 대한 시각화
[1] "English_United States.1252"
`summarise()` regrouping output by 'continent' (override with `.groups` argument)

  1. 대한민국 일일 검사수와 검사수와 7일 이동평균선(new_tests_smoothed) 시각화
  • 일일 검사수는 막대도표로 표시
    • 7일 이동 평균선은 빨강색으로 표시
[1] "English_United States.1252"
Warning: Removed 2 rows containing missing values (position_stack).

  1. 2020년 5월 31일 기준 상위 24개 국가의 국가 별 확진자 대비 COVID-19 검사 수(전체, 전체 검사수/전체 확진자 수)를 도식화
    • 막대도표 사용
필요한 패키지를 로딩중입니다: RColorBrewer

References

Wilkinson, Leland. 2012. “The Grammar of Graphics.” In Handbook of Computational Statistics, 375–414. Springer.