ggplot2 - 02 Drawing Graphs

by Minho Lee — on  ,  ,  , 

cover-image

ggplot2

저번 글에서는 ggplot2가 어떻게 동작하는지를 위주로 살펴보았습니다. 이번에는 그래프가 에러없이 뜨는데 만족하지 않고 원하는 형태로 그래프를 만들 수 있도록 다른 옵션들을 조작하는 방법을 살펴보겠습니다.




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

Parameter

parameter를 추가하면 geom의 형태를 변경하거나 stat이 적용되는 방법을 바꿀 수 있습니다. 에스테틱을 직접 적용하거나 각 함수마다 주어지는 옵션을 변경하게 됩니다. 에스테틱은 aes함수 안에서 쓰이면 데이터의 값에 매핑되지만, 밖에서 쓰일 경우에는 해당 요소를 전부 변경합니다. 예를 들어 geom_point(aes(size = var))var 데이터의 값에 따라 점의 크기가 변하게 됩니다. 하지만 geom_point(size = 3) 의 경우에는 모든 점의 크기가 3으로 고정됩니다.

iris_plot +
  geom_point(size = 3, colour = 'red') +
  geom_smooth()

에스테틱 중에서 좌표를 나타내는 xy를 제외하면

colour(또는 color)는 점이나 선 색상이나 면의 테두리 색을 결정합니다

fill은 면의 색상을 결정합니다

alpha는 색의 투명도를 나타냅니다


에스테틱은 아니지만 각 함수의 세부적인 내용을 조정하는 parameter들도 존재합니다.

geom_smooth의 경우에는 method = 'lm'으로 지정하면 추세선을 직선으로 그려줍니다.

iris_plot +
  geom_point(size = 3, colour = 'red') +
  geom_smooth(method = 'lm')

linetype 옵션은 선의 모양을 변경할 수 있게 합니다.

iris_plot +
  geom_point(size = 3, colour = 'red') +
  geom_smooth(linetype = 2)

se 옵션을 끄면 standard error의 범위를 표현하지 않습니다.

iris_plot +
  geom_point(size = 3, colour = 'red') +
  geom_smooth(se = FALSE)


각각의 함수들에는 적용할 수 있는 다양한 parameter들이 있습니다. 각 parameter들에 대한 자세한 설명은 역시 이 곳의 링크로 남겨놓는 편이 좋겠네요. 아직 이번 1월에 업데이트된 공식 1.0.0 버전에 추가된 내용은 반영되지 않은 것 같습니다만, 그래도 상당히 많은 예제를 볼 수 있습니다.




Position Adjustment

positiongeom이 보여지는 형태를 바꿉니다. 막대그래프라면 막대가 누적으로 쌓일지, 옆에 나란히 놓일지 결정할 수 있습니다. 산점도라면 여러 점들이 겹쳐있을때 각 좌표에 일정 난수를 더해서 흩어져보이게 만들 수도 있습니다.


ggplot(data = mpg, aes(displ, hwy)) +
  geom_point(position = "jitter") +
  geom_smooth()

position = ‘jitter’를 적용하면 각 x,y값에 난수를 더해서 점이 겹치지 않도록 합니다. geom_point(position='jitter')geom_jitter() 로 줄여서 쓸 수 있습니다


ggplot(mtcars,
  aes(factor(cyl), fill = factor(vs))) +
  geom_bar(position="stack")

막대그래프에서 position = ‘stack’은 각 막대를 쌓아서 누적된 형태로 보여줍니다.

ggplot(mtcars,
  aes(factor(cyl), fill = factor(vs))) +
  geom_bar(position="fill")

position = ‘fill’은 비율을 나타내는 누적 막대를 보여줍니다.

ggplot(mtcars,
  aes(factor(cyl), fill = factor(vs))) +
  geom_bar(position="dodge")

position = ‘dodge’는 각 막대를 옆으로 나열합니다


postion을 적용하지 않을 때에는 position = ‘identity’ 옵션이 사용됩니다. 기본값이 postion = ‘identity’인 함수를 사용하고 있다면 position옵션을 생략할 수 있습니다.

그리고, position을 더 상세하게 지정하고 싶다면 position_옵션이름 으로 지정된 함수에 parameter를 적용하면 됩니다. position_dodge의 경우에는 어느 정도 간격으로 떨어뜨려 놓을지 정할 수 있고, position_jitter에서는 난수를 어느 정도로 적용할 지 결정할 수 있습니다.

dodge = position_dodge(0.3)

ggplot(sleep, aes(x=ID, y=extra, group=group)) + 
  geom_line(position = dodge) + 
  geom_point(position = dodge, size=4, fill='white', shape=21)
## ymax not defined: adjusting position using y instead
## ymax not defined: adjusting position using y instead

위에서는 position_dodge를 사용하지 않으면 ID=5일 때 점이 겹쳐보입니다. 일부러 점을 떨어져있게 만들고 싶다면 위와 같이 position_dodge 함수를 적용시킬 수 있습니다.




Scales

Scale은 데이터의 값이 그래프의 에스테틱에 대입되는 과정을 조절하고 guide(축과 범례 등)가 어떻게 표시되는지 결정한다고 저번 글에서 말씀드렸습니다. 스케일과 관련된 함수는 기본적으로는 scale_에스테틱_적용방법으로 이름이 정해집니다. 스케일을 조절하는 함수는 에스테틱의 종류만큼이나 다양하게 존재하지만, 어느 정도 규칙적인 함수명 덕분에 비교적 쉽게 검색해서 적용이 가능합니다.


우선 본격적으로 관련 함수들에 대해서 알아보기 전에 xlim, ylim 함수를 살펴보겠습니다.

ggplot(data = mpg, aes(displ, hwy)) +
  geom_point() +
  geom_smooth() +
  xlim(4,6)
## Warning: Removed 153 rows containing missing values (stat_smooth).
## Warning: Removed 153 rows containing missing values (geom_point).

xlim(), 또는 ylim()함수를 이용하면 화면에 보이는 그래프의 범위를 보여줄 수 있습니다. 화면에 나오지 못하는 데이터가 생긴다면 경고메세지가 발생하지만 그래프는 문제없이 그려집니다.




다음으로는 색상과 관련된 scale에 대해서 살펴보려고 합니다. 아래 예제에서는 fill을 기준으로 설명하겠지만, fill을 colour로 바꾸기만 하면 많은 경우에 동일한 방식으로 적용할 수 있습니다.

dia_bar <- ggplot(diamonds, aes(x=cut, fill = cut)) + geom_bar()

dia_bar +
  scale_fill_brewer()

xxx_brewer로 끝나는 색상관련 scale 함수들은 RColorBrewer패키지를 이용해서 색상을 지정합니다.

RColorBrewer::display.brewer.all()

display.brewer.all() 함수를 통해 사용가능한 색 조합의 이름과 색상들을 살펴볼 수 있습니다. 값의 높고 낮음을 보여줄 수 있는 Sequential, 서로 다른 범주나 그룹들을 구분지어 보여줄 수 있는 Qualitative, 어느 중심 값을 기준으로 얼마나 떨어져 있는지를 보여주는 Diverging 의 순서로 정리가 되어 있습니다. 현재 표현하고자 하는 데이터의 형태를 잘 살펴보고, 적절한 색조합을 적용시키면 됩니다.

원하는 색조합을 찾았다면, palette 옵션에 조합의 이름을 넣어서 색상을 적용할 수 있습니다.

dia_bar +
  scale_fill_brewer(palette = 'Paired')

dia_bar +
  scale_fill_brewer(palette = 'Accent')




다음은 축에 대한 scale함수를 사용해보겠습니다. 연속적인 수치 자료가 y축에 있을 때 스케일은 scale_y_continuous함수를 적용할 수 있습니다. x축이라면 y를 x로 바꾸면 되고, 이산형자료라면 continuous가 discrete로 바뀝니다.

위에서 xlim 함수를 살펴보았는데요. scale_x_continuous 안에 limits 옵션을 지정하면 동일한 효과를 얻을 수 있습니다. xlim이 적용되었던 예제를 scale_x_continuous로 표현하면 다음과 같습니다.

ggplot(data = mpg, aes(displ, hwy)) +
    geom_point() +
    geom_smooth() +
    scale_x_continuous(limits=c(4,6))
## Warning: Removed 153 rows containing missing values (stat_smooth).
## Warning: Removed 153 rows containing missing values (geom_point).

산점도 같은 경우에는 그래프로 표현하는 범위를 강제하더라도 문제가 없겠지만, 막대 그래프 같은 경우에는 위와 같은 방식을 사용하면 막대 자체가 표현이 되지 않을 수 있으니 유의하시기 바랍니다.


trans옵션은 변수변환을 스케일 차원에서 조절할 수 있게 해줍니다. trans = log10옵션을 적용하면 y축에 log10 함수를 적용합니다. scale_y_log10 처럼 자주 쓰이는 함수들은 미리 함수들이 지정되어 있기도 하지만 옵션에서 사용하면 사용가능한 함수의 이름을 입력하는 방식으로 사용할 수 있습니다.

dia_bar +
  scale_fill_brewer(palette = "Accent") +
  scale_y_continuous(trans = "log10")


breaks옵션은 눈금에 표시되는 항목을 지정할 수 있게 해줍니다.

dia_bar +
scale_y_continuous(breaks = c(5000, 15000))




Coordinate System

좌표계의 경우 아무런 값이 지정되지 않으면 기본값으로 Cartesian을 적용합니다(coord_cartesian()). coord_flip()을 이용해 x축과 y축을 뒤바꿀 수 있고, coord_polar()를 사용하면 극좌표계로 변환시킬 수 있습니다.

dia_bar +
  coord_flip()

dia_bar +
  coord_polar()

그래프에서 보이는 축의 범위를 조절하려고 할 때 위에서 했던 대로 scale을 변경할 수도 있지만, 좌표계를 직접 변형시키는 방법이 있습니다. 하지만 두 개의 방식에는 큰 차이가 있는데, scale을 변경하면 해당 스케일을 벗어나는 데이터는 제거하고 그래프를 그립니다. 따라서 boxplot의 경우에는 남아있는 데이터로 box가 새로 그려질 것이고 막대그래프의 경우에는 데이터의 범위를 벗어나는 막대는 막대 자체가 그려지지 않습니다.

# 'Ideal'의 막대가 그려지지 않는다
dia_bar + scale_y_continuous(limits=c(0,15000))

ggplot(InsectSprays, aes(x=spray, y=count)) + 
  geom_boxplot() +
  scale_y_continuous(limits=c(0,15))
## Warning: Removed 16 rows containing non-finite values (stat_boxplot).

반면에 좌표를 직접 수정하는 경우에는 그래프를 일단 그린 다음에 입력한 범위만 확대하거나 축소하는 등 변형을 시킵니다. 그래서 그래프의 모양이 변하거나 하지 않습니다.

# 'Ideal'의 막대가 그려진다. 대신 15000 이후로는 보이지 않는다
dia_bar +
  coord_cartesian(ylim=c(0,15000))

ggplot(InsectSprays, aes(x=spray, y=count)) + 
  geom_boxplot() +
  coord_cartesian(ylim=c(0,15))




coord 항목을 신경써서 적용해야 할 때가 또 있습니다. 바로 지도를 그릴 때인데요. 지도를 그릴 때는 기본적으로 위도와 경도가 직교좌표계에 그려지는데, coord_map()을 사용하면 지도의 투영 방식을 적용하여 ggplot 그래프를 그릴 수 있습니다.

maps 패키지에서 지도를 받아온 후에 좌표계를 지정하지 않고 그려보겠습니다.

library(maps)
asia = map_data('world', region = c('Japan', 'China', 'North Korea', 'South Korea'))

ggplot(asia, aes(x = long, y = lat, group = group)) +
  geom_polygon(fill = 'white', colour = 'black')


다음은 coord_map 함수를 사용합니다. 기본 투영법은 mercator입니다. 위도선이 나타나는 간격이 달라지는 것을 볼 수 있습니다.

ggplot(asia, aes(x = long, y = lat, group = group)) +
  geom_polygon(fill = 'white', colour = 'black') +
  coord_map()


?mapproject을 통해서 적용할 수 있는 다양한 투영법과 적용할 수 있는 옵션을 찾아볼 수 있습니다. 아래에서는 그 중 몇 가지만 함께 살펴보도록 하겠습니다.

ggplot(asia, aes(x=long, y=lat, group = group)) +
  geom_polygon(fill = 'white', colour = 'black') +
  coord_map("orthographic")

ggplot(asia, aes(x=long, y=lat, group = group)) +
  geom_polygon(fill = 'white', colour = 'black') +
  coord_map("polyconic")




Facetting

facet을 적용하면 데이터의 부분집합들을 하위 그래프로 분리해서 그릴 수 있습니다.

facet_wrap()을 사용하면 하위 그래프들이 수평으로 나열되고, facet_grid()은 수직과 수평으로 각각 다른 변수를 지정할 수 있습니다.

mtc_point <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point()

mtc_point +
  facet_wrap(~cyl)

두 개 이상의 변수를 동시에 지정하면 각 변수들의 경우의 수에 맞게 그래프를 그려줍니다.

이렇게 많은 숫자의 그래프가 그려질 때 ncol 옵션을 이용하면 한 화면에 보여질 그래프 열의 개수를 조정할 수 있습니다.

mtc_point +
  facet_wrap(~cyl+gear, ncol = 2)

mtc_point +
  facet_grid(gear~cyl)


facet_wrap의 경우에는 scales 옵션을 이용하면 각 그래프의 축을 고정시킬지 그래프별로 다르게 할지 결정할 수 있습니다.

scales = ‘fixed’는 각 그래프 모두 축이 일정하게 그려집니다.

scales = ‘free’는 각 그래프의 데이터 범위에 맞게 조정해서 그립니다.

scales = ‘free_x’는 x축은 데이터 범위에 맞게 조절하고, y축은 고정시킵니다. ‘free_y’ 옵션도 마찬가지로 사용할 수 있습니다.

mtc_point +
  facet_wrap(~cyl, scales = "fixed")

mtc_point +
  facet_wrap(~cyl, scales = "free")

mtc_point +
  facet_wrap(~cyl, scales = "free_x")


facet_grid에서도 마찬가지로 scales 옵션에 ‘free’‘free_x’, ‘free_y’ 등을 적용할 수 있습니다. facet_grid에서는 추가적으로 space 옵션을 추가할 수 있는데, 기본적으는 각 그래프의 크기가 동일하게 그려지지만, space = ‘free’ 옵션이 지정되면 데이터의 범위에 따라 그래프의 크기도 변경됩니다.

mtc_point +
  facet_grid(gear~cyl, scales = "free_x")

mtc_point +
  facet_grid(gear~cyl, scales = "free")

mtc_point +
  facet_grid(gear~cyl, scales = "free", space = "free")





여기까지 해서 ggplot 객체를 구성하는 layer, scale, coord, facet까지 훑어보았습니다. 이제 어느 정도 원하는 대로 ggplot 그래프를 그릴 수 있게 되었습니다. 다음 글에서는 ggplot 그래프에 저장된 테마를 적용하는 방법과 stat이 생성하는 변수 등 앞에서 제대로 다루지 않았던 항목들을 살펴보려고 합니다.


이전글 - ggplot2 01

다음글 - ggplot2 03

Comments