ggplot2 - 01 Grammar of Graphics

by Minho Lee — on  ,  ,  , 

cover-image

ggplot2

몇 번의 포스팅을 거쳐서 ggplot2의 원리와 사용법에 대해서 이야기해보려고 합니다. ggplot2는 분명 아무것도 모르고 접근하기에는 어느 정도 진입장벽이 있는 패키지라고 생각합니다. 받아들이는 데이터의 형식이 정해져 있고, 단순한 산점도나 막대그래프를 그릴 때에도 요소들을 맵핑하고 레이어를 얹어주는 작업을 해주어야 합니다. 그리고 함수나 옵션들이 굉장히 많기 때문에 무작정 패키지를 배워보겠다고 tutorial을 찾아보다가는 길을 잃어버릴 수도 있습니다. 하지만 ggplot2는 그 일관적인 체계 덕분에 더 강력한 힘을 발휘합니다. 일단 그 구조를 이해하게 되면 처음 시도해보는 시각화 방식도 무리없이 적용해 볼 수 있습니다. 또, input 데이터의 형식이 일정하기 때문에 다양한 형태의 차트를 일정한 형태의 문법으로 데이터의 변경을 최소화시키면서 만들어 볼 수 있습니다.




Data to Graph

데이터를 통해 그래프를 그리는 과정은 다시 말하면 데이터의 속성을 그래프의 시각적인 속성에 대입(대응)시키는 것입니다.

예를 들어, 시계열 자료인 종합주가지수를 그래프로 그린다고 해보겠습니다. 시간에 따른 시계열 변화를 선그래프로 표현해보려고 합니다. 이 때 시간이라고 하는 변수는 그래프에서 X축에 대입된다면, 수치(연속형)형 자료인 종합주가지수는 Y축에 대응됩니다. 한국과 일본의 주가지수를 비교해 볼 수도 있을 텐데요. 이 경우에 국가라는 변수는 서로 다른 직선으로 표현되어야 하는데, 색상을 다르게 주거나 선의 형태를 실선/점선으로 구분하여 국가를 구분해서 보여줄 수 있습니다.

R에서 기본적으로 제공하는 그래픽 함수들은 사용하기가 편리합니다. 물론 이것은 상황에 따라서 달라지긴 하겠지만 iris 데이터의 Scatter plot matrix는 plot(iris) 라는 짧은 한 줄짜리 코드로 실행시킬 수 있습니다.

그리고 plot 함수는 어느 정도 데이터의 형태를 확인해서 그에 적합한 시각화 방식을 제공합니다. plot(Nile)의 경우에는 시계열 자료라는 특성에 맞게 시간에 따른 선그래프를 그려줍니다


이처럼 R이 기본적으로 제공하는 그래픽 함수들은 간편하게 그래프를 그릴 수 있게 해줍니다. 그렇다면 이 함수들은 무엇이 문제일까요. 실제로 데이터를 가지고 그래프를 그려보겠습니다.


R에서 기본으로 제공하는 데이터는 data()로 확인할 수 있습니다. 기본 데이터 중에서 BOD 데이터를 가지고 막대그래프와 선그래프를 그려보려고 합니다.

plot(BOD)


plot함수로 그려놓고 보니 우리가 원하던 선의 형태가 아닙니다. 선 모양으로 강제하기 위해서는 type = 'l'옵션을 추가해 주어야 합니다.

plot(BOD, type = 'l')


선 그래프를 완성했습니다. 그러면 이번에는 막대그래프를 그려보려고 합니다. 막대그래프를 그리려면 barplot 함수를 사용해야 합니다.

barplot(BOD)

실행시켜보면 에러 메세지가 뜹니다. ‘height’는 반드시 벡터 또는 행렬이어야 합니다 라는 메세지가 나옵니다.

그러면 행렬로 데이터를 변환시킨 후에 사용해 보겠습니다. as.matrix()를 사용합니다.

barplot(as.matrix(BOD))


이번에도 원하는 모양의 그래프가 나오지 않았습니다. 행렬로 변환은 시켰는데 행과 열이 뒤바뀐 것 같습니다. 행과 열을 뒤바꾸려면 함수 t (transpose) 를 사용하면 됩니다.

barplot(
  t(as.matrix(BOD))
  )


그려놓고 보니 생각지도 않던 누적 막대 그래프입니다. plot 함수는 알아서 Time 변수를 X축으로 인식했는데 barplot은 그렇지 않은 것 같습니다. 우리는 demand 변수만을 높이로 해서 막대를 그리면 되기 때문에 아래와 같이 그래프를 완성하겠습니다.

barplot(BOD$demand)


여기까지의 과정을 살펴보겠습니다. 분명 각각의 그래프를 그릴 때에는 정말 단순한 코드로 괜찮은 그래프를 쉽게 얻을 수 있었습니다. 하지만 문제는 선그래프를 그리고나서 동일한 데이터의 막대그래프를 그릴 때인데요. 완전히 다른 함수에, 받아들이는 데이터의 형태도 다르면서, 내부의 옵션들 또한 내용이 많이 다릅니다. 각각의 함수는 쉽게 사용할 수 있다고 하지만, 새로운 그래프를 그리려면 매번 처음부터 공부를 해야할 것 같습니다.

또, 위에서 보이지는 않았지만 lines, points, abline 등의 함수를 이용해 그래프를 겹쳐서 그리다가 실수라도 할 경우에는 low level 함수인 plot부터 다시 그려야 합니다. 차트가 복잡해지고 다양한 시각화를 원할 수록 기본 그래픽 함수는 답답해 질 수 있습니다.


그렇다면 동일한 데이터를 ggplot2를 이용해 막대와 선 그래프를 그려보겠습니다. 각 문법에 대한 자세한 설명은 뒤에서 다룰 것이기 때문에, 여기서는 선과 막대를 그릴 때 코드가 어떻게 달라지는지를 중점적으로 살펴보면 됩니다.

library(ggplot2)

ggplot(data = BOD, aes(x=Time, y=demand))+
  geom_line()

ggplot(data = BOD, aes(x=Time, y=demand))+
    geom_bar(stat='identity')


ggplot2를 이용해서 그래프를 그릴 경우에는 데이터를 변형시키지 않고도 다양한 방식으로 그래프를 그릴 수 있습니다. 그리고 일정한 문법구조와 비슷한 옵션들을 가지고 있기 때문에 새로운 시각화를 할 때의 비용이 적습니다.





ggplot2가 그래프를 그리는 방식


iris 데이터에서 Sepal.LengthSepal.Width 데이터로 산점도를 그린 후에 Species변수에 따라 색상을 달리하여 ggplot2 그래프를 그려보았습니다. 여기서 ggplot2 그래프의 구성을 그림으로 살펴보면 다음과 같습니다.


1. Data

그래프를 그리려는 데이터는 iris로 결정했습니다. 데이터 내의 변수는 데이터 프레임의 열로 저장되어 있어야 합니다.

ggplot2가 요구하는 형태(Tidy data)에 대한 자세한 내용은 다음 문서에서 확인할 수 있습니다.


2. Mapping

그러면, 데이터의 요소와 그래프의 요소를 대응시키는 과정이 발생합니다. 여기서

Sepal.Length - X축

Sepal.Width - Y축

Species - 점의 색상

이 대응됩니다. 여기서 대응은 무조건 1:1로 대응될 필요는 없고, 그리려고 하는 그래프가 필수적으로 요구하는 대응요소만 만족시키면 됩니다. 하나의 변수가 여러 가지 시각적 요소(ggplot2에서는 이것을 에스테틱 Aesthetic 이라고 합니다)에 대응될 수도 있습니다.


3. Geometric Object

그리고 나면 어떤 형태의 그래프를 그릴지 지정해야 합니다. ggplot2에서는 이것을 Geometric Object, 줄여서 geom이라고 합니다. 여기서는 산점도(Scaterplot)를 그렸는데, ggplot2에서는 geom_point 함수를 사용합니다.


4. Position

그래프의 형태를 지정했으면 그래프에서 각 도형이 어떤 식으로 배치될 지를 결정할 수 있습니다. 이 옵션이 바로 position입니다. 막대그래프나 선 그래프라면 누적 그래프를 그리거나 할 때 position 옵션을 조정해서 형태를 바꿀 수 있습니다. 여기서는 특별한 배치가 필요없기 때문에 그대로(‘identity’) 배치합니다.


5. Statistical Transformation

마지막으로 값이 어떻게 그래프에 반영되는지 결정하는 옵션이 있습니다. Statistical Transformation, 줄여서 stat 옵션입니다. 히스토그램과 같이 구간내에 존재하는 값의 개수를 세거나 밀도를 계산하는 등, 주어진 값을 변형시켜서 그래프에 반영시킬 때 사용합니다. 여기서는 특별한 변환 없이 값을 그대로(‘identity’) 사용합니다.





ggplot2의 구성

위에서 살펴본 다섯 가지 구성 요소들은 하나의 레이어를 구성합니다. 그리고 하나 이상의 레이어만 구성되면 ggplot2는 우리에게 그래프를 출력합니다. 레이어 이외에 ggplot2의 그래프를 구성하는 요소는 Scale, Coordinate System, Facet, Guide가 있습니다.


Scale

Scale은 데이터의 값이 그래프의 에스테틱에 대입되는 과정을 조절하고 guide(축과 범례 등)가 어떻게 표시되는지 결정합니다. 보통은 ggplot2가 알아서 scale을 추가하지만 원하는 사항에 대해서는 명시해 주면 그래프에 반영시킬 수 있습니다. scale을 조절하면 logsqrt 등의 변수 변환을 ggplot2 상에서 할 수 있고, fill이나 colour 등의 에스테틱에서 색상을 사용자가 지정할 수 있게 됩니다.


Coordinate System

여기서는 좌표를 결정하는 에스테틱들이 어떻게 연결되는지를 결정합니다. 기본값은 직교좌표계(Cartesian)로 지정되어 있습니다. statgeom이 결정되면 좌표계를 변경할 수 있습니다. 또, Cartesian에서 x축과 y축을 바꾸는 것도 이 부분에서 변경할 수 있습니다.


Facet Specification

데이터를 특정 변수를 기준으로 하는 부분집합들로 쪼개서 small multiple의 형태로 그릴 수 있게 합니다. iris 데이터를 기준으로 말하자면, 위에서 했던 것처럼 색상으로 구분하지 않고 Species별로 각각의 그래프를 따로 그리게 됩니다.


Guides

가이드는 그래프를 보는 사람이 그래프의 시각적인 속성들을 어떻게 데이터와 연관지어서 볼 수 있는지 안내하는 역할을 합니다. 눈금을 표시하고 축에 이름표를 달거나 범례를 작성하는 등 그래프를 보고 데이터를 떠올리는 데 도움을 주는 항목들입니다.


결국 ggplot2의 그래프는

Layer + Scale + Coordinate System + (Facet) + (Guide)

의 형태로 결정이 됩니다. Scale과 Coord 도 사실은 기본값이 주어져 있기 때문에, Layer에만 신경써도 어느 정도 원하는 그래프를 얻을 수 있습니다.





ggplot2 그래프 그리기

ggplot2::layer

ggplot() +
  layer(data = iris,
        mapping = aes(x = Sepal.Length, y = Sepal.Width, colour = Species),
        geom = 'point',
        stat = 'identity',
        position = 'identity')


Shortcut

layer 함수를 이용하면 그래프를 그리는데 필요한 요소들을 레이어에 대입시켜서 원하는 그래프를 얻을 수 있습니다. 하지만 실제로 사용할 때는 자주 사용하는 요소들을 묶어서 미리 만들어놓은 함수들을 사용하게 됩니다. 아래 코드는 위에서 layer함수를 사용했을 때와 같은 결과물을 나타냅니다.

ggplot()+
  geom_point(data = iris, aes(x=Sepal.Length, y=Sepal.Width, colour=Species))

geom_pointgeom='point', stat='identity', position='identity'가 기본값으로 정해져 있는 함수입니다. 이러한 shortcut 들을 사용하여 더 편리하게 그래프를 그릴 수 있습니다.


Multiple Layers

ggplot()+
  geom_point(data = iris, aes(x=Sepal.Length, y=Sepal.Width)) +
  geom_smooth(data = iris, aes(x=Sepal.Length, y=Sepal.Width))

이와 같이 여러개의 레이어를 중복시켜서 그릴 수도 있습니다. 이 때, 공통적으로 반영되는 요소들은 미리 ggplot() 안에 정의해두면 geom이나 stat을 추가할 때 자동적으로 상속받게 됩니다. 또, ggplot을 이용해 만든 결과물은 객체로 저장할 수 있습니다. Mapping되는 부분까지만 객체로 저장해두고 다양한 차트를 그려보는 것도 가능합니다.

iris_plot = ggplot(data = iris, aes(x=Sepal.Length, y=Sepal.Width))

iris_plot +
  geom_point() +
  geom_smooth()




ggplot2를 소개하는 첫 번째 글에서는 Grammar of Graphic을 기반으로 어떻게 ggplot2가 그래프를 그리는지를 위주로 살펴보았습니다. 다음 글에서는 parameter와 position을 수정하여 그래프의 형태를 변경하고, scale, coord 등을 변경하는 등 그래프에 대해 세밀한 조작을 하는 과정에 대해서 살펴보겠습니다




다음글 - ggplot2 02 - drawing graphs


참고자료

R Graphics Cookbook

http://docs.ggplot2.org/current/

http://ggplot2.org/resources/2007-past-present-future.pdf

http://ggplot2.org/resources/2007-vanderbilt.pdf

Comments