聰明不如鈍筆
총명불여둔필
assignment KindeR

최대한 친절하게 쓴 R로 그래프 그리기(feat. ggplot2)

제목에서 느끼실 수 있는 것처럼 이 포스트는 '초심자'용입니다. 이미 ggplot2를 능숙하게 다루지만 갑자기 문제가 생겨서 해법을 찾으려는 분께는 거의 도움이 되지 않을 확률이 매우 매우 높습니다.

 

R는 아주 뛰어난 시각화 프로그램입니다.

 

해들리 위컴 박사가 개발한 ggplot2 패키지와 함께라면 더더욱 그렇습니다. (ggplot 뒤에 2가 붙은 건 그냥 버전 2.0이라고 생각하셔도 됩니다.)

 

이번 포스트에서는 ggplot2로 그래프를 그리는 '원리'에 대해 알아보겠습니다.

 

이 원리를 잘 응용하면 원하시는 거의 모든 그래프를 그릴 수 있을 겁니다.

 

다소 생뚱맞아 보이지만 이 kini's Sportugese 포스트에 있는 카바디 경기장 모양도 ggplot2로 그렸습니다.

 

인터넷 포털 사이트에서 ggplot2를 찾아 이 포스트를 찾아 오신 분이라면 이미 R가 무엇인지 잘 알고 계실 터.

 

그래도 혹시 모르시는 분들께 R 홈페이지에 올라온 대로 설명드리면 R는 통계 계산과 그래픽에 활용하는 무료 소프트웨어 환경(R is a free software environment for statistical computing and graphics)"입니다.

 

따라서 누구든 이 다운로드 페이지에서 원하시는 R를 내려 받아 컴퓨터에 설치하실 수 있습니다.

 

이 글을 쓰고 있는 2018년 8월 현재 최신 버전은 3.5.1이며 마이크로소프트(MS) 윈도에 이 버전을 설치하고자 하시는 분은 이 링크를 눌러서 내려받으시면 됩니다.

 

이 포스트는 '최대한 친절하게'를 표방하고 있지만 프로그램 설치법은 다들 아시리라 믿고 넘어가겠습니다.

 

설치가 끝나고 R를 실행하시면 아래와 같은 화면이 나타납니다. 창 제목에 나와 있는 것처럼 이 창을 'R 콘솔(Console)'이라고 부릅니다.

 

저 '>' 표시 뒤에 명령어를 입력하는 걸로 프로그래밍(코딩)을 진행할 수 있습니다. 코딩은 '내가 이러저러한 게 하고 싶다'고 컴퓨터에게 알려주는 행위를 뜻합니다.

 

그러니까 제가 "print('Hello, World!')"라고 쓴 건 Hello, World!를 (화면에) 출력하고 싶다는 뜻을 컴퓨터에게 알려준 게 됩니다.

 

"Hello, World!" 프로그램은 코딩을 처음 배울 때 제일 많이 쓰는 기본 예제입니다. 

 

이 22글자도 치기 귀찮으시다면 '1+1'을 한번 입력해 보세요. 그러면 2라는 값을 표시할 겁니다.

 

정말 R를 깔아서 할 게 없으실 때는 계산기로 쓰셔도 된다는 뜻입니다. 물론 컴퓨터에 이미 계산기 프로그램이 들어 있는 게 함정이기는 하지만 말입니다. (네, 재미없는 농담 죄송합니다.)

 

이제 print에 이어 두 번째 명령어를 배울 때가 됐습니다. 그 명령어는 패키지를 설치하는 'install.packages()'입니다.

 

패키지는 문자 그대로 R 기본 프로그램에는 들어 있지 않은 각종 기능 묶음이라고 생각하시면 쉽습니다. ggplot2도 시각화 전문 패키지입니다.

 

ggplot2는 다음과 같은 명령으로 설치하실 수 있습니다.

 

install.packages('ggplot2')

 

이때 ggplot2를 따옴표(' 또는 ")로 묶어주시는 걸 잊으시면 안 됩니다.

 

따옴표로 묶지 않으면 ggplot2라는 오브젝트를 찾을 수 없다는 에러 메시지가 뜹니다. (이건 ggplot2 자체를 변수 이름으로 받아들이기 때문에 생기는 문제인데, 여기서는 중요한 게 아니니 일단 패스하겠습니다.) 

 

정상적으로 입력을 마치셨다면 패키지를 내려 받을 서버를 고르라는 선택창이 뜨는데 일반적으로는 그냥 엔터를 누르셔도 됩니다.

 

설치가 끝났다고 패키지를 곧바로 쓸 수 있는 건 아닙니다. 패키지를 메모리에 불러오는 과정을 거쳐야 합니다.

 

이때는 library() 명령어를 쓰시면 됩니다. 아래 그림처럼 입력하면 됩니다. (이때는 따옴표가 없어도 괜찮습니다.)

 

library('ggplot2')

 

축하합니다. 여러분은 이제 막 ggplot2 세계로 진입하는 데 성공하셨습니다.

 

어떤 이유로든 확신이 들지 않으신다면 'ggplot()'라고 한 번 입력해 보세요. 이때 새로운 창이 하나 뜬다면 정말 성공하신 겁니다.

 

 

성문 기초 ggplot2 문법

R 같은 프로그램을 흔히 '프로그래밍 언어'라고 부릅니다. 그래서 이 언어에도 문법이 있고, ggplot2는 ggplot2만의 문법이 있습니다.

 

그래프를 그리려면 일단 데이터가 필요합니다. 그래프는 대부분 2차원 공간에 그리니까 x축과 y축에 각각 데이터를 할당해야 합니다.

 

그리고 이 데이터를 어떤 모양으로 그릴지 결정해야 합니다. 데이터에 따라 어떤 때는 막대 그래프가 좋을 거고, 선 그래프가 좋을 때도 있을 겁니다.

 

여기서 끝이 아닙니다. 미적(aesthetic) 요소도 필요합니다. 산포도를 그린다고 치면 점 크기를 어떤 기준으로 정할 건지 색깔은 어떻게 할 건지 컴퓨터에게 알려줘야 하는 겁니다.

 

이 내용을 그림으로 정리하면 아래 그림 같은 결과가 나옵니다.

 

아직도 이해가 잘 가지 않는 분이 계실지 모르니 실제로 그래프를 하나 그려볼까요?

 

ggplot2를 불러오신 상태에서 (지금까지 따라오셨다면 이미 그런 상태입니다) 아래 코드를 한번 입력해 보세요. 그러면 새 창에 이런 그래프가 나타날 겁니다.

 

ggplot(data=mtcars, aes(x=disp, y=mpg)) + geom_point(aes(size=hp, color=wt))

 

한번 더 축하드립니다. 여러분은 지금 인생 처음으로 ggplot2 그래프를 완성하셨습니다.

 

코드를 다시 한번 볼까요?

 

ggplot(data=mtcars, aes(x=disp, y=mpg)) + geom_point(aes(size=hp, color=wt))

 

맨 처음에 ggplot를 써서 그래프를 그릴 거라고 컴퓨터에게 알려줍니다. 이어서 괄호 안에 어떤 데이터를 쓸 건지, x축과 y축은 어떤 열을 활용할 것인지도 담아줍니다.

 

여기서는 R에 기본적으로 들어 있는 차종별 데이터(mtcars)에서 자료를 가져와서 x축에는 배기량(dist), y축에는 연비(mpg)를 넣으라고 입력했습니다.

 

이때 x 축과 y 축을 나타내기 전에 aes라고 쓴 건 위에서 말씀드린 이 역시 미적 요소에 들어가기 때문. 기능적으로 aes는 변수에서 값을 가져와서 처리하라는 뜻입니다.

 

만약 여기까지만 쓰시고 실행을 하시면 그냥 x축에 배기량, y축에 연비만 표시할 뿐 메인 영역(?)은 그냥 빈 공간으로 남아 있게 됩니다.

 

이 메인 영역 모양을 결정하는 게 바로 geom_point(aes(size=hp, color=wt)입니다. ggplot2에서는 이렇게 더하기(+) 표시로 이어가면서 그래프에 필요한 요소를 추가합니다.

 

저 코드가 뜻하는 건 뭘까요? 네, 맞습니다. 점 그래프(산포도)를 그리되 마력(hp)을 기준으로 점 크기를 정하고, 무게(wt)에서 자료를 가져와서 색깔을 정하라는 뜻입니다.

 

geom_point로 점 그래프를 그릴 수 있다면 막대 그래프는 어떻게 그려야 할까요? geom_bar가 (가장 모범에 가까운) 정답입니다.

 

선 그래프는? 네, (이번에도 가장 모범에 가까운 정답은) geom_line입니다.

 

예상하신 것처럼 여기서 geom은 기하학적인(geometric) 특징이라는 뜻입니다. 

 

참고로 이번에는 산포도 하나만 그렸기 때문에 코드를 ggplot(data=mtcars, aes(x=disp, y=mpg, size=hp, color=wt)) + geom_point() 이렇게 쓰셔도 100% 똑같은 결과를 얻으실 수 있습니다. 

 

ggplot2 특징 가운데 하나는 이 코드를 변수에 넣을 수 있다는 것. R에서는 어떤 값을 변수에 넣을 때 '=' 또는 '<-'로 표시합니다.

아래는 이 코드를 p라는 변수에 넣으라는 내용입니다.

 

p <- gplot(data=mtcars, aes(x=disp, y=mpg, size=hp, color=wt)) + geom_point()

 

이렇게 쓰시고 p만 치셔도 위에서 본 것과 똑같은 그래프가 나옵니다.

 

지금까지는 ggplot2가 데이터, 기하학적 요소, 미적 요소 세 가지만 쓰는 것처럼 말씀드렸지만 사실 하나가 더 있습니다. 바로 통계학적 결과를 추가할 수 있습니다.

 

이 그래프를 잘 보시면 배기량이 늘어날수록 연비는 줄어드는 경향이 있다고 눈치채실 수 있을 겁니다.

 

한번 다음과 같이 입력해 보실까요? 그러면 이미 우리가 알고 있던 그래프 위에 국소 회귀분석(loess) 방식으로 그린 추세선을 추가한 그래프가 나타납니다.

 

p + stat_smooth(color='black', fill='grey')

 

어? 그런데 이때는 color와 fill을 aes()로 묶지 않았습니다. 변수에서 값을 가져오는 게 아니라 사용자가 특정 값을 지정하고 싶을 때는 이런 식으로 그냥 쓰시면 됩니다.

 

이때 주의하실 건 색깔 이름(여기서는 black, grey)를 따옴표로 묶어야 한다는 점입니다. 아니면 black, grey라는 변수로 이해하기 때문입니다. (R에서 쓰는 색깔 이름에 관해서는 이 링크를 참조하시면 좋습니다.)

 

여기서 사과를 한 번 드려야 할 것 같습니다. 지금까지 살펴 본 네 가지 이외에도 +로 연결할 수 있는 게 더 있기 때문입니다. 축 범위를 조정할 수도 있고, 가로-세로 비율도 조정할 수 있습니다. 

 

또 패싯(facet)을 추가하는 것도 가능합니다. 패싯은 특정 기준에 따라 그래프를 여러 개로 나누는 것 뜻합니다.

 

예를 들어 이 그래프를 실린더(cyl) 숫자에 따라 나누고 싶다면 이렇게 쓰면 됩니다. 그러면 아래 그림처럼 실런더 숫자별로 그래프를 세 개로 나눠 출력합니다.

 

p + stat_smooth(color='black', fill='grey') + facet_wrap(~cyl)

 

~cyl은 이렇게 세로로 나누라는 뜻. 가로로 나누고 싶을 때는 facet_wrap(cyl~.)라고 쓰시면 됩니다.

 

이상이 ggplot2로 그래프를 그리는 기본 원리입니다. 먼저 데이터를 지정해주시고 geom_모양(), stat_특징(), facet_분류() 등을 계속 +로 연결만 하시면 그만입니다. 그렇다면 geom, stat, facet 뒤에 어떤 게 붙을 수 있는지 알아봐야겠죠?

 

풀 버전은 이 공식 링크를 찾아 가시면 확인하실 수 있습니다. 그래프를 그릴 때마다 그때그때 찾아보고 싶으시면 이 '커닝 페이퍼'를 참고하시면 좋습니다. (그림을 저장하시면 크기를 키워서 보실 수 있습니다. 위, 아래 두 장입니다.)

 

 

 

성문 기본 ggplot2 #1

자, 이제 기초 문법 개념 정리는 끝나셨을 줄로 믿고 간단히 실제 그래프를 그려보겠습니다.

 

이번에는 1967~2014년 미국 경제 관련 내용을 담고 있는 economics 데이터를 쓸 겁니다. ggplot2를 설치하셨다면 자동으로 들어있습니다.

 

데이터 첫 여섯 줄을 보여주는 명령어 head를 활용해 head(economics)라고 입력하면 다음 같은 결과가 나타납니다.

 

head(economics)
## # A tibble: 6 x 6
##   date         pce    pop psavert uempmed unemploy
##   <date>     <dbl>  <dbl>   <dbl>   <dbl>    <dbl>
## 1 1967-07-01  507. 198712    12.6     4.5     2944
## 2 1967-08-01  510. 198911    12.6     4.7     2945
## 3 1967-09-01  516. 199113    11.9     4.6     2958
## 4 1967-10-01  512. 199311    12.9     4.9     3143
## 5 1967-11-01  517. 199498    12.8     4.7     3066
## 6 1967-12-01  525. 199657    11.8     4.8     3018

 

각 변수가 어떤 내용을 뜻하는지 궁금하시다면 help(economics)라고 입력해 보세요. 그러면 인터넷 브라우저가 관련 내용을 담은 페이지로 안내할 겁니다.

 

우리는 이 중에서연 날짜(date)별 실업자 숫자(unemploy)로 선 그래프를 그려보겠습니다. 선 그래프를 그리려면 geom_line을 쓰면 됩니다. 기억하고 계시죠? 이렇게 말입니다.

 

ggplot(data=economics, aes(x=date, y=unemploy)) + geom_line()

 

이 선 그래프 색깔을 바꾸고 싶다. 그러면 어떻게 하면 될까요?

네, 맞습니다. geom_line(color='원하는 색상') 형태로 바꾸시면 됩니다. (반드시 따옴표가 필요한 것 기억하고 계시죠?)

 

같은 방식으로 geom_line(lwd=숫자)로 쓰시면 선 굵기를 바꿀 수 있습니다.

 

ggplot(data=economics, aes(x=date, y=unemploy)) + geom_line(color='#FFAA00', lwd=1)

 

물론 선 모양(대시)도 바꿀 수 있습니다. 이때는 linetype='선 모양'을 쓰시면 됩니다.

선 모양은 아래 그림 가운데서 고르실 수 있습니다. (물론 이 그림도 ggplot2로 그렸습니다.)

 

이 그래프에 평균선을 넣으면서 linetype를 써볼까요? 이 그래프에는 가로로 길게 평균선을 넣어야 할 겁니다. 이때는 geom_hline() 함수를 씁니다. 세로로 길게 그릴 때는 geom_vline()입니다.

 

geom_hline()에는 y값을 넣어줘야 합니다. 그냥 'geom_hline(yintercept=값)'처럼 쓰면 그만입니다. (geom_vline에는 xintercept가 들어갑니다.)

 

우리는 이 값에 평균을 넣으려 합니다. r에서 평균을 구하는 함수는 mean()입니다. 구체적으로 우리가 계산하고 싶은 건 economics라는 변수 가운데 employ라는 열 평균입니다.

 

이를 r 문법에 따라 쓰면 mean(economics$unemploy)입니다. '$'이 바로 특정 열을 선택하라는 구실을 하는 겁니다.

 

이상을 종합하면 위에 있던 코드에 geom_hline(yintercept=mean(economics$unemploy))를 더하면 됩니다. 선 모양도 바꾸기로 했으니까 linetype='dashed'도 추가해 보겠습니다.

 

ggplot(data=economics, aes(x=date, y=unemploy)) + geom_line(color='#FFAA00', lwd=1) + geom_hline(yintercept=mean(economics$unemploy), linetype='dashed')

 

그러면 여기서 선 그래프를 막대 그래프로 바꾸려면 어떻게 해야 할까요?

네, 그렇습니다. geom_line 부분을 geom_bar로 바꾸면 됩니다.

 

아, 아직 기다리세요. 저 코드에서 geom_line을 geom_bar로 곧바로 바꾸면 'Error: stat_count() must not be used with a y aesthetic'이라고 에러 메시지가 뜹니다. 

 

막대 그래프에 어떤 값을 표시할지 결정하지 않았기 때문입니다. 우리는 그냥 이 숫자 그대로 막대 그래프를 그리는 걸로 충분합니다. 이때 쓰는 표현은 stat='identity'입니다. 그러면 코드와 결과는 이렇게 됩니다.

 

ggplot(data=economics, aes(x=date, y=unemploy)) + geom_bar(stat='identity', color='#FFAA00', lwd=1) + geom_hline(yintercept=mean(economics$unemploy), linetype='dashed')

 

x축 공간은 좁은 데 데이터는 많다(574개) 보니 geom_area를 쓰는 것과 차이가 없는 형태로 나오기는 했지만 분명 막대 그래프 맞습니다.

 

만약 이때 geom_bar() 부분과 geom_hline() 부분 순서를 바꾸면 어떻게 될까요? 그러면 이런 그림이 나옵니다.

 

차이점 아시겠습니까? 네, 레이어 순서가 바뀌면서 평균선이 막대 그래프 뒤로 숨었습니다. 어떤 그래프를 위에 표시하고 싶으시면 나중에 더하시면 되는 겁니다.

 

이제 이 그래프를 저장해보겠습니다.

 

저장은 ggsave()라는 함수로 합니다. 그냥 ggsave('파일명')이라고 쓰시기만 하면 현재 창에 떠 있는 그림을 저장합니다.

이때 파일 확장자로 png나 pdf 가운데 하나를 넣으셔야 합니다.

 

만약 특정한 크기(또는 비율)로 그림을 저장하고 싶으실 때는 ggsave('파일명', width=가로, height=세로) 형태를 취하시면 됩니다.

 

여기에 'dpi=숫자'를 더하면 해상도까지 결정할 수 있습니다. dpi=100을 넣으시면 정확하게 원하는 크기로 그림이 나옵니다.

 

그러니까 이 그래프를 graph.png라는 이름에 1600 × 900 픽셀짜리로 저장하고 싶으시다면 ggsave('graph.png', width=16, height=9, dpi=100)이라고 쓰시면 됩니다.

 

이 그림은 딱 저 코드로 그린 건 아니고 이 블로그 크기에 맞게 16:9 비율로 조정한 겁니다. 컴퓨터에서 보고 계시다면 가로폭 700 픽셀 기준입니다.

 

성문 기본 ggplot2 #2

막대 그래프 부분이 아쉬우니까 조금 더 그려보겠습니다. 이번에는 다시 mtcars 데이터로 돌아갑니다.

 

아, 그러고 보니 mtcars가 어떻게 생겼는지 확인을 해보지 않았네요. 이럴 때 쓰는 명령어는? 네, head입니다.

 

head(mtcars)
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

 

이번에는 차량별 연비를 가지고 막대 그래프를 그리겠습니다.

 

여기서 주의해야 할 건 이 데이터에는 차량 모델 이름을 나타내는 열이 따로 없다는 겁니다. 행 이름을 가지고 열을 하나 더 만들기로 합니다.

 

행 이름을 확인하는 함수는 rownames()입니다. 이를 name이라는 열을 만들어 넣으려면:

 

mtcars$name <- rownames(mtcars)

 

이렇게 치시면 됩니다. 그러면 아래 그림처럼 잘 들어온 걸 확인하실 수 있습니다.

 

head(mtcars)
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
##                                name
## Mazda RX4                 Mazda RX4
## Mazda RX4 Wag         Mazda RX4 Wag
## Datsun 710               Datsun 710
## Hornet 4 Drive       Hornet 4 Drive
## Hornet Sportabout Hornet Sportabout
## Valiant                     Valiant

 

이제 막대 그래프를 그리겠습니다. 이제 이 정도 코드는 그냥 쓰실 수 있으시겠죠?

 

ggplot() + geom_bar(data=mtcars, aes(x=name, y=mpg), stat='identity')

 

이번에는 코드가 이전하고 조금 다릅니다. 예전에는 ggplot() 안에 속성을 넣었는데 이번에는 geom_bar() 안으로 옮겼습니다.

 

지금은 데이터가 하나뿐이지만 만약 서로 다른 데이터를 가져와 그래프 하나에 넣고 싶으실 때가 있다면 이런 식으로 활용하시면 됩니다.

 

단, 이러면 이대로 또 불편한 점이 생기기 때문에 다음부터는 원래 스타일로 돌아가겠습니다.

 

그래프도 뭔가 어수선합니다. 그냥 이름 순서대로 그래프가 나왔기 때문입니다. 이 데이터는 차량별 연비를 제공하고 있으니까 연비 순서대로 정렬을 하면 좋겠죠

 

그래서 코드를 이렇게 조금 고쳤습니다. 그랬더니 이렇게 오른쪽으로 갈수록 값이 올라가는 그래프가 나왔습니다

 

ggplot(data=mtcars, aes(x=reorder(name, mtcars$mpg), y=mpg)) + geom_bar(stat='identity')

 

코드에서 뭐가 바뀐 건지 보이시나요

 

네, reorder(name, mtcars$mpg)라는 값을 x축에 넣었습니다. 이건 name을 x축에 넣을 때 그 mpg가 작은 것부터 앞에 오도록 순서를 조정하라는 뜻입니다.

 

만약 값이 큰 것부터 작은 것 순서로 정렬하게 싶을 때는 reorder(name, -mtcars$mpg)라고 마이너스(-)만 붙이면 됩니다.

 

ggplot(data=mtcars, aes(x=reorder(name, -mtcars$mpg), y=mpg)) + geom_bar(stat='identity')

 

아직 문제가 있습니다. x축 텍스트가 서로 겹쳐 제대로 보이지 않습니다. 이때는 theme() 함수 도움을 받아야 합니다. (뭐가 자꾸자꾸 튀어 나옵니다 ㅡ.,ㅡ)

 

ggplot(data=mtcars, aes(x=reorder(name, -mtcars$mpg), y=mpg)) + geom_bar(stat='identity') + theme(axis.text.x = element_text(angle = 90))

 

이러면 글씨는 보이지만 글씨를 읽으려면 고개를 돌려야 한다는 불편함이 있습니다.

 

게다가 요즘에는 많은 분들이 모바일 그러니까 세로로 긴 화면을 통해 그래픽을 접하시기 때문에 이렇게 가로로 된 그래픽이 꼭 최선이라고 할 수 없습니다.

 

저는 개인적으로 세로로 그래프를 뽑는 데 최선을 다하는 스타일입니다. 한마디로 그래프 전체를 90도 회전시키는 게 낫다는 뜻입니다. 이 때 쓰는 함수는 coord_flip()입니다.

 

ggplot(data=mtcars, aes(x=reorder(name, -mtcars$mpg), y=mpg)) + geom_bar(stat='identity') + coord_flip()

그런데 이렇게 바꾸니 위쪽에 연비가 좋은 모델이 오는 게 더 낫다는 느낌이 들지 않으십니까?

 

그렇게 바꾸려면 reorder에 들어 있는 마이너스 표시만 빼면 됩니다.

 

아울러 세로가 길도록 비율을 바꾸면 이런 그림을 얻을 수 있습니다.

 

ggplot(data=mtcars, aes(x=reorder(name, mtcars$mpg), y=mpg)) + geom_bar(stat='identity') + coord_flip()

 

x, y축 제목이 그대로 있으니까 좀 이상합니다. 지워보겠습니다.

 

이때는 labs()가 필요합니다. labs(x='x축 제목', y='y축 제목')처럼 쓰시면 됩니다.

 

아, 너무 오랫동안 ggplot2 그래프를 함수에 넣어두는 걸 쓰지 않았으니 먼저 넣고 시작해 보겠습니다.

p <- ggplot(data=mtcars, aes(x=reorder(name, mtcars$mpg), y=mpg)) + geom_bar(stat='identity') + coord_flip()
p + labs(x='x', y='y')

 

이상합니다. 분명 x축에 x, y축에 y라고 제목을 달았는데 결과는 거꾸로 나왔습니다.

 

이건 우리는 coord_flip() 함수를 통해 축을 바꿨지만 R는 여전히 원래 입력한 코드를 그대로 기억하고 있기 때문입니다.

 

겉으로 드러난 모양새만 바뀐 겁니다. 이런 상황에서 축 제목을 입력할 때는 주의할 필요가 있습니다.

 

그렇다면 축 제목을 전부 없애고 싶을 때는 어떻게 할까요?

 

축 제목 부분을 그냥 빈 따옴표로 남겨두시면 그만입니다. 이런 식으로 말입니다.

 

p + labs(x='', y='')

 

이제 그래프 제목을 달아보겠습니다. 걱정하실 필요 없습니다. labs()를 떠나지 않으니까요.

 

제목은 labs()안에 title을 써서 넣으면 됩니다. 이번에는 그냥 '차량별 연비'라고 제목을 달겠습니다.

 

p + labs(x='', y='', title='차량별 연비')

 

제목 크기가 너무 작다고 생각하시면 다시 theme() 함수를 쓰시면 됩니다. 아래처럼 입력하시면 제목이 커진 걸 확인하실 수 있을 겁니다.

 

p + labs(x='', y='', title='차량별 연비') + theme(plot.title = element_text(size=18))

 

이렇게 그리고 나니 막대 그래프 끝에 연비를 넣고 싶다는 생각이 듭니다.

 

이때는 (또 뭐가 튀어 나오겠죠?) geom_text()가 해답입니다. 일단 지금까지 그린 걸 다시 p에 넣고 텍스트만 더하면:

 

p <- p + labs(x='', y='', title='차량별 연비') + theme(plot.title = element_text(size=18))
p + geom_text(aes(label=mpg), size=3, hjust=1.25, color='#FFFFFF')

 

코드 맨 마지막에 나온 geom_text(aes(label=mpg), size=3, hjust=1.25, color='#FFFFFF')를 뜯어 보어 보겠습니다.

 

일단 mpg 값을 가져다가 레이블(label)로 쓰라는 명령으로 시작합니다.

 

글씨 크기는 3으로 하고, 이 텍스트는 그래프 끝에서 가로로 1.25 떨어진 지점에 위치하도록 정렬합니다.

 

글씨 색깔은 '#FFFFFF' 그러니까 하얀색입니다.

 

이때 만약 특정 차량 모델을 다른 색으로 강조하고 싶으면 어떻게 할까요?

 

이럴 때는 ggplot2가 레이어 형태로 계속 그래프를 쌓을 수 있다는 사실을 이용하면 됩니다. 그러니까 위에 있는 그래프를 일단 그리고 그 위에 다시 그래프를 얻어도 되는 겁니다.

 

'혼다 시빅(Honda Civic)'을 강조해 보겠습니다.

 

p + geom_bar(data=mtcars[mtcars$name=='Honda Civic', ], aes(x=name, y=mpg), fill='#5CBED2', stat='identity') + geom_text(aes(label=mpg), size=3, hjust=1.25, color='#FFFFFF')

중간이 복잡합니다. 이상한 건 바로 data=mtcars[mtcars$name=='Honda Civic', ] 이 부분입니다.

 

R에서 변수 이름 뒤에 []를 쓰면 특정 조건을 만족하는 자료를 뽑아 오라는 뜻이 됩니다. 예컨대 mtcars[1, ]라고 치면 다음처럼 나옵니다.

 

mtcars[1, ]
##           mpg cyl disp  hp drat   wt  qsec vs am gear carb      name
## Mazda RX4  21   6  160 110  3.9 2.62 16.46  0  1    4    4 Mazda RX4

 

어디서 보신 것 같지 않으신가요? 위에서 head(mtcars)를 썼을 때 나온 첫 번째 줄입니다. '변수이름[행, 열]'이라고 쓰면 어떤 변수에서 특정 데이터를 가져올 수 있습니다.

 

mtcars$name=='Honda Civic'은 mtcars에서 각 행별로 name이 Honda Civic인지 아닌지 판가름해달라는 뜻입니다. R 콘솔에 이렇게 입력하면 이런 결과가 나옵니다.

 

mtcars$name=='Honda Civic'
##  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [12] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
## [23] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

 

그러면 19번째 행이 그렇다(True)다고 나옵니다. 이를 일일이 확인하는 대신 [] 안에 넣어서 그 부분을 찾으라고 컴퓨터에게 시키는 겁니다.

 

따라서 data=mtcars[mtcars$name=='Honda Civic', ]는 mtcars 중에서 name이 Honda Civic인 19번째 행을 가지고 오라는 뜻이 됩니다.

 

만약 다른 차량을 강조하고 싶으실 때는 'Honda Civic'만 그 차량 이름으로 바꾸면 됩니다.

 

 

성문 종합 ggplot2를 기다리며…

맨 처음에 말씀드린 것처럼 이 포스트는 ggplot2 초심자에서 이 패키지로 그래프를 그리는 원리를 소개하는 게 목적이었습니다. 그래서 ggplot2에 이미 발을 담그고 계셨던 분께는 '뭐, 이 정도로 벌써 끝나나' 하는 느낌만 남길지도 모르겠습니다. 

 

맞습니다. 세상에는 ggplot2로 그린 아주 멋진 그래프가 아주 많이 있습니다. 블로그 포스트 하나로 그 그래프를 모두 소개해 드린다는 건 불가능에 가까운 일입니다.

 

그래도 확실히 말씀드릴 수 있는 건 ggplot2로 그린 어떤 그래프도 이 포스트에서 다룬 기본 원리를 크게 벗어나지는 않는다는 점입니다.

 

아래처럼 지구본 위에 세계에서 제일 긴 항공 노선을 그리는 것도 마찬가지입니다.

 

이렇게 좀 더 있어 보이는 그래프를 ggplot2로 그리는 법을 알고 싶으시면 이 페이지를 찾아보시면 도움이 될 수 있습니다.

 

영문 페이지이기는 하지만 어떤 그래프를 어떻게 그리는지 소스를 자세히 소개하고 있습으니 어렵지 않게 확인하실 있을 겁니다.

 

지도에 점 찍고, 선 긋고, 색칠하는 건 이 포스트를 참조하셔도 좋습니다.

 

전에도 말씀드렸지만 프로그래밍 언어로 시각화를 하면 코드만 알고 있으면 바로 그 그래프를 100% 똑같이 재현할 수 있다는 장점이 있습니다.

 

이번 포스트를 바탕으로 아주 멋진 그래프를 그리는 데 성공하셨다면 댓글 등을 통해 알려주셔도 좋습니다.

 

아, 혹시 (저처럼) ggplot2 기본 글꼴이 마음에 들지 않으신다면 이 블로그 포스트가 도움이 될 수 있습니다.

 

그럼 모두들 Happy Charting! -_-)/

 

데이터 과학 입문서 '친절한 R with 스포츠 데이터'를 썼습니다

어쩌다 보니 '한국어 사용자에게 도움이 될지도 모르는 R 언어 기초 회화 교재'를 세상에 내놓게 됐습니다. 책 앞 부분은 '한국어 tidyverse 사투리' 번역, 뒷부분은 'tidymodels 억양 따라하기'에 초점

kuduz.tistory.com

 

댓글,

KindeR | 카테고리 다른 글 더 보기