8  그래프 문법

기존 베이스 R 그래픽(Base R Graphics)은 R 프로그래밍 언어에 기본 내장된 저수준 그래픽 함수들을 총칭한다. 화가가 캔버스에 그림을 그려나가는 과정과 비슷하게 사용자는 저수준 그래픽 함수를 사용해서 데이터 시각화 그래픽을 제작해 나간다. 베이스 R 그래픽에서 사용자가 직접 모든 그래프 각 요소를 개별적으로 지정하고 조정해야 한다. 예를 들어, 축, 레이블, 색상, 점의 크기 등을 모두 사용자가 직접 설정해야 하는데, 마치 화가가 캔버스에 선을 그리고, 색을 칠하고, 세부사항을 추가하는 것과 매우 유사하다.

베이스 R 그래픽은 매우 유연하여 그래프의 모든 측면을 통제할 수 있다는 장점이 있지만, 이러한 유연성은 동시에 단점으로 작용한다. 그래프를 생성하는 과정이 복잡하고 시간이 많이 걸리며, 코드 가독성이 떨어질 뿐만 아니라, 그래프 스타일의 일관성을 유지하기도 어렵다. 베이스 R 그래픽의 한계를 극복하기 위해 그래프 문법(Grammar of Graphics)에 기반한 ggplot2와 같은 고수준 패키지가 개발되었다. 그래프 문법을 따르는 ggplot2 그래픽 시스템을 사용하면 그래픽 요소들을 추상화하고 체계화하여 더 간단하고 직관적인 방식으로 그래프를 생성할 수 있다.

8.1 그래프 문법 역사

릴랜드 윌킨슨(Leland Wilkinson)의 “The Grammar of Graphics”는 1999년 첫 출간된 이후 데이터 그래픽(data graphics)에 많은 영향을 주어 ggplot2, Polaris → Tableau, Vega-Lite 등의 형태로 우리 곁에 다가왔다.

“그래프 문법”은 R ggplot2, 타블로(Tableau)의 전신 폴라리스(Polaris), 베가-라이트(Vega-Lite)에 영감을 주었고, 데이터 시각화 분야 전반에 영향을 미쳤을 뿐만 아니라 자바스크립트 시각화 라이브러리 D3.js의 발전에도 간접적인 영향을 주었다. 그래프 문법이 짧은 기간 동안 데이터 시각화 분야에 미친 영향을 그림 8.1 에서 확인할 수 있다.

ggplot2는 주로 정적 그래프를 생성하는 데 사용되지만, 추가 패키지(plotly, gganimate 등)를 사용하면 상호작용 인터랙티브 그래픽 기능도 추가할 수 있다. Vega-Lite는 상호작용 시각화를 위한 고급 문법을 제공하고, D3.js는 사용자 정의 상호작용 시각화를 구현하는 데 장점이 있다.

graph TD
   A[그래프 문법] -->|영감| B[R ggplot2]
   A -->|영감| C[Polaris]
   A -->|영향| D[Vega-Lite]
   E[자바스크립트] --> F[D3.js]
   A --> I[데이터 시각화<br> 분야]
   I -->|영향| F
   C -->|선행| G[Tableau]
   D -->|고급 문법| H[상호작용 시각화]
   F -->|사용자 정의<br>시각화| H
   B -.->|추가 패키지| H

  subgraph ggplot2
    B -->|R 시각화| J[정적 그래프]
  end

    classDef modern fill:#fff,stroke:#333,stroke-width:2px,color:#333,font-family:MaruBuri,font-size:12px;
    classDef emphasize fill:#8CBDE3,stroke:#333,stroke-width:3px,color:#333,font-family:MaruBuri,font-size:15px,font-weight:bold;
    classDef subgraphStyle fill:#f0f8ff,stroke:#333,stroke-width:2px,color:#333,font-family:MaruBuri,font-size:15px;
    
    class B,C,D,E,F,G,H,I,J modern
    class A emphasize
    class ggplot2 subgraphStyle
그림 8.1: 그래프 문법 진화 과정

기존에는 다양한 그래픽 객체를 만들기 위해 그래프 종류별로 개별적인 사용법을 배워야 했다. 그래프 종류가 적을 때는 유용하지만, 그래프 종류가 많아질수록 매번 새로운 사용법을 익혀야 하므로 확장성이 크게 떨어지는 한계가 있었다.

이러한 문제를 해결하기 위해서 데이터 그래픽 객체를 보다 일반화된 방식으로 다룰 수 있는 그래프 문법(grammar of graphics)이 도입되었다. 그래프 문법은 데이터 그래픽 객체를 8개 계층으로 분해하여 각 계층을 조립하는 방식으로 그래프를 생성한다.

이러한 접근 방식을 취하게 되면, 그래프 종류에 관계없이 일관된 방법으로 그래프를 제작할 수 있다. 그래프 문법을 활용하면 데이터 특성에 맞는 최적의 그래프를 유연하게 생성할 수 있어 혁신적인 방법론이라고 할 수 있다.

예를 들어, 그림 8.2 에 제시된 원그래프, 선그래프, 막대그래프, 산점도를 생성하는 코드를 보면, 각 그래프별로 입력값과 사용법이 다르다. 그러나 ggplot2를 사용하면 데이터와 그래프 계층을 분리하여 각 계층을 조립하는 방식으로 그래프를 생성할 수 있어 일관성을 유지하고 코드 재사용성을 높일 수 있다.

그림 8.2: ggplot이 필요한 이유

8.2 그래프 문법

그래프 문법은 데이터 시각화에 있어 중요한 구조를 제공하며, 총 8개의 다른 층으로 구성된다. 각 층은 데이터를 시각적으로 표현하는 과정에서 독특한 기능과 목적을 가지고 있다. 각 층별로 데이터 즉 데이터프레임과 에스테틱(aesthetics), 기하형상(geometries), 통계적 변환(statistical transformations), 척도(scales), 좌표계(coordinate systems), 포지셔닝(positioning), 작은 창(faceting) 및 테마(theming)와 같은 그래픽 요소의 결합을 정의한다. 이렇게 각기 다른 층이 결합되어 데이터의 시각적 표현이 완성된다.

graph LR
    subgraph A [데이터와 에스테틱]
    AA[데이터프레임] -->|매핑| AB[에스테틱]
    end
    subgraph B [핵심 구성요소]
    AB --> BA[기하형상]
    AB --> BB[통계적 변환]
    AB --> BC[척도]
    end
    subgraph C [레이아웃과 테마]
    BA --> CA[좌표 시스템]
    BB --> CA
    BC --> CA
    CA --> CB[포지셔닝]
    CA --> CC[작은 창]
    CB --> CD[테마]
    CC --> CD
    end

    classDef modern fill:#fff,stroke:#333,stroke-width:2px,color:#333,font-family:MaruBuri,font-size:12px;
    classDef emphasize fill:#8CBDE3,stroke:#333,stroke-width:3px,color:#333,font-family:MaruBuri,font-size:15px,font-weight:bold;
    classDef subgraphStyle fill:#f0f8ff,stroke:#333,stroke-width:2px,color:#333,font-family:MaruBuri,font-size:15px;
    
    class AA,AB,BA,BB,BC,CA,CB,CC,CD modern
    class B emphasize
    class A,B,C subgraphStyle
그림 8.3: ggplot 그래프 문법 구성요소

8.2.1 데이터

그래프 문법 ggplot에서 데이터는 깔끔한 데이터(tidy data)를 가정한다. 이를 위해서 기존 wide형태의 데이터는 키값(key-value) long 형태로 변환하여 준비한다.

그림 8.4: 깔끔한 데이터 wide, long 데이터

8.2.2 매핑

깔끔한 데이터가 준비되면 다음 단계로 칼럼에 해당하는 각 변수를 aes() 함수를 사용해서 에스테틱(aesthetics) aes(x=x, y=y, color=z, ...)와 같은 방식으로 데이터프레임 변수를 축에 매핑한다.

그림 8.5: 데이터를 그래프에 매핑

8.2.3 통계량

범주형 그래프를 시각화할 때는 빈도수를 통계량으로 활용해야 한다. 연속형 변수의 히스토그램을 그릴 때는 구간별 빈도수를 계산하는 것이 중요하다. 상자그림(boxplot)의 경우, 각 분위수와 중위수, 그리고 사분위수 범위를 포함하여 수염의 끝을 계산함으로써 정확한 상자그림을 시각화할 수 있다. 이러한 계산은 그래프의 정확성과 해석을 위해 필수적으로 거쳐야 하는 과정이다.

그림 8.6: 그래프별 기본설정 통계량

8.2.4 척도

그래프에서 X축과 Y축의 척도를 자동으로 인식하는 데는 한계가 있으므로, 필요에 따라 적절한 형태로 설정하는 것이 중요하다. scale_<x, y, color, fill, ...>_<유형>() 형식의 구문을 사용한다. 예를 들어, Y축 변수에 로그 척도가 적합한 경우 scale_y_log10() 함수를 사용하여 변수의 특성에 맞는 척도로 설정한다. 마찬가지로, 변수가 날짜나 시간일 경우 scale_x_date() 또는 scale_x_datetime() 함수를 활용해 적절하게 설정한다.

그림 8.7: aes 매핑된 축 척도지정

8.2.5 기하형상

기하형상(geometries)은 ggplot2에서 시각화의 핵심 요소 중 하나다. 예를 들어, 범주형 변수를 aes() 함수로 지정한 후 geom_*() 형식의 함수를 사용하여 이 변수를 다양한 그래프 형태로 표현한다. 원그래프, 막대그래프, 점그래프 등 다양한 시각화 객체를 선택하여 데이터를 명확하고 효과적으로 나타낼 수 있다.

그림 8.8: 기하형상 지정

8.2.6 작은 창

작은 창(faceting)은 ggplot2에서 다차원 데이터를 다루는 효과적인 방법이다. 이를 통해 원본 데이터를 그룹으로 나눠 각 그룹을 작은 창에 동일한 형태의 시각화 객체로 표현한다. 중요한 것은 모든 작은 창에서 동일한 유형의 그래프를 사용한다는 점으로 이런 일관성은 데이터를 비교 분석하는 데 도움이 된다.

그림 8.9: 그룹으로 쪼갠 작은 창(facet)

8.2.7 좌표계

좌표계(coordinate)는 ggplot2에서 데이터 시각화 후반 처리 단계에 해당한다. 깔끔한 데이터를 그래프에 매칭하고 시각화한 후, 상황에 따라 좌표계를 변경하는 것이 필요할 수 있다. coord_fixed(), coord_polar(), coord_flip() 등의 함수를 통해 특정 영역을 확대하거나, 데카르트 좌표계에서 극좌표계로 변경하고, X축과 Y축을 뒤집는 등의 작업을 수행할 수 있다. 좌표계 변경을 통해 데이터를 다양한 관점에서 보여줄 수 있게 하여 분석의 깊이를 더하고 커뮤니케이션 효과도 높일 수 있다.

그림 8.10: 좌표계 변환

8.2.8 분위기 풍

테마, 분위기 풍(theme)은 ggplot2에서 그래프 외양을 다듬는 중요한 단계다. 이 단계는 데이터 시각화 과정과 직접적인 연관이 없으며, 대신 그래프의 외형적인 부분을 개선하는 역할을 한다. 여기서는 적절한 색상 팔레트를 적용하고 글꼴을 변경하는 등의 작업을 수행한다. 이러한 조정 작업은 그래프의 전반적인 미적 품질을 향상시켜 결과물의 이해도와 시각적 매력을 증가시키는 중요한 역할을 한다.

그림 8.11: tufte 분위기 풍(theme)
library(ggthemes)

default_g <- mtcars %>% 
  ggplot(aes(x=disp, y=mpg)) +
    geom_point()

tufte_g <- mtcars %>% 
  ggplot(aes(x=disp, y=mpg)) +
    geom_point() +
    theme_tufte()

ragg::agg_jpeg("images/tufte_gg.jpeg", width = 10, height = 7, units = "in", res = 600)
gridExtra::grid.arrange(default_g, tufte_g, nrow=1)
dev.off()
그림 8.12: “ggplot2tufte 분위기 풍(theme) 적용 예시”

8.3 ggplot 확장

ggplot 확장은 기본 ggplot 그래프 객체를 더욱 다양하게 활용하는 것을 의미한다. 한 번에 2개 이상의 그래프를 합치거나, 다른 방식으로 배열하고, 특정 부분을 강조하거나 주석을 추가하는 것이 가능하다. 또한 애니메이션과 인터랙티브 기능을 통해 보다 동적이고 상호작용이 가능한 시각화를 만들 수 있다. patchwork, gganimate, plotly, ggrepel, gghighlight 등의 패키지를 활용하여 ggplot 그래프를 확장할 수 있다.

그림 8.13: ggplot2 패키지 확장

8.4 요약

그래프 문법은 데이터 시각화를 위한 체계적인 구조를 제공하며, 데이터와 에스테틱, 기하형상, 통계적 변환, 척도, 좌표계, 포지셔닝, 작은 창, 테마 등 8개 층으로 구성된다. 각 층은 데이터를 시각적으로 표현하는 과정에서 고유한 역할을 수행하며, 이를 조합하여 최종적인 그래프를 생성한다.

ggplot2에서는 데이터를 그래프에 매핑하고, 적절한 통계량과 척도를 설정하며, 다양한 기하형상을 선택하여 데이터를 효과적으로 시각화할 수 있다. 또한 작은 창을 활용하여 다차원 데이터를 비교 분석할 수 있으며, 좌표계 변경을 통해 데이터를 다양한 관점에서 탐색할 수 있다.

그래프의 외양을 다듬는 테마 설정은 데이터 시각화 과정과 직접적인 연관은 없지만, 그래프의 미적 품질과 이해도를 높이는 데 중요한 역할을 한다. 마지막으로 ggplot 확장 패키지를 활용하면 그래프를 조합하거나, 애니메이션 및 인터랙티브 기능을 추가하여 더욱 풍부한 시각화를 만들 수 있다.