gganimate 예: 한국의 인구 구조 변화
http://www.ggplot2-exts.org/gallery/ 링크에 가보면 ggplot2
의 확장 패키지들이 소개되어 있습니다. 이 중 첫 번째 패키지는 gganimate
입니다. Hans Rosling 선생께서 우리의 눈과 귀를 즐겁게 해주었던 TED 강연도 이미 10여년 전이네요. gganimate
은 차트로 움직이는 그림(애니메이션)을 만들기 위해 쓰입니다.
gganimate
!
설치
install.packages('gganimate')
install.packages('gifski')
install.packages('png')
사용방법
기본적으로 ggplot2
와 동일하다.
애니메이션은 사실 여러 그림을 연달아 보여주는 것에 지나지 않는다. 따라서 gganimate
은 ggplot2
의 Aesthetic mapping을 그대로 따르면서 시간에 따라 달라지는 변수를 정해준다.
+ transition_time(year)
그리고 여러 그림을 연달아 보여줄 때 그림 사이의 변화를 부드럽게 하기 위한 방법이 필요하다. (다른 방법은 ?enter_exit
으로 확인 가능하다.)
+ enter_fade()
실례
자료
datPop <- data.table::fread('population.csv', encoding='UTF-8')
그림 한 장
먼저 2019년(올해)의 자료를 그려보자.
자료가 가로형이므로, ggplot
을 사용하기 위해 세로형으로 변형한다.
library(dplyr); library(tidyr)
iyear = 2019
head(datPop)
## age male female age2 year ## 1: 79세 6471 12315 79 1960 ## 2: 78세 7281 11200 78 1960 ## 3: 77세 9132 14453 77 1960 ## 4: 76세 10586 13331 76 1960 ## 5: 75세 11865 14565 75 1960 ## 6: 74세 14077 19490 74 1960
datPopAni <- datPop %>% mutate(year=as.integer(year)) %>% gather(key='gender', value='population', male, female)
library(ggplot2)
ggplot(data=datPopAni %>% filter(year==iyear),
aes(x=age2,
y=ifelse(gender=='male',
population, -population), fill=gender)) +
geom_bar(stat='identity', width=0.9,alpha=0.8) +
#geom_freqpoly(stat='identity') +
#geom_bar(data=datPop_ %>% filter(gender=='female'), stat='identity') +
#geom_bar(data=datPop_ %>% filter(gender=='male'), aes(y=..count..*(-1))) +
#scale_y_continuous(labels = paste0(as.character(c(seq(2, 0, -1), seq(1, 2, 1))), "m")) +
scale_x_continuous(name='나이(세)') +
scale_y_continuous(name='인구(만명)', labels=c(50, 25, 0, 25, 50), limits=c(-500000,500000)) +
scale_fill_manual(name='성별', labels=c('여', '남'), values=c('darkorange', 'dodgerblue2'))+
theme_minimal()+
coord_flip() +
#theme(legend.position='bottom', title=element_text(size=16)) +
labs(title = paste0('한국의 인구 구조(',iyear,'년)'))
애니메이션
이제 애니메이션을 만들기 위해 두 가지를 결정해야 한다.
- 시간에 해당하는 변수를 정한다. 여기서는
year
변수를 사용했다.(+transition_time(year)
) - 화면 전환 방법을 정한다. 여기서는
+enter_fade()
를 사용했다.
library(gganimate)
ggplot(datPopAni, aes(x=age2,
y=ifelse(gender=='male',
population/10000, -population/10000), fill=gender)) +
geom_bar(stat='identity') +
#geom_bar(data=datPop_ %>% filter(gender=='female'), stat='identity') +
#geom_bar(data=datPop_ %>% filter(gender=='male'), aes(y=..count..*(-1))) +
#scale_y_continuous(labels = paste0(as.character(c(seq(2, 0, -1), seq(1, 2, 1))), "m")) +
geom_bar(stat='identity', width=0.9,alpha=0.8) +
scale_x_continuous(name='나이') +
scale_y_continuous(name='인구(만명)', labels=c(50, 25, 0, 25, 50)) +
coord_flip() +
labs(title = '한국의 인구 구조 변화 ({frame_time} 년)')+
scale_fill_manual(name='성별', labels=c('여', '남'), values=c('darkorange', 'dodgerblue2'))+
theme_minimal() +
theme(legend.position='bottom', title=element_text(size=16)) +
theme(legend.position='bottom') +
transition_time(year) +
enter_fade() -> p
이제 결과 p
로 이미지 화일을 만들어보자.
animate(p, rendere=gifski_renderer(loop=TRUE), width= 600, height=600)
##
## Rendering [>--------------------------------------] at 5.7 fps ~ eta: 17s
## ...
## Rendering [=======================================] at 5.1 fps ~ eta: 0s
##
## Frame 1 (1%)
## ...
## Frame 100 (100%)
## Finalizing encoding... done!
여기서 loop=TRUE
는 애니메이션이 마지막 화면에서 정지한다. 만약 loop=FALSE
로 바꾸면 애니메이션은 무한 루프를 돈다(애니메이션이 끝나면 다시 시작하기를 반복한다).
마지막으로 화일로 저장하고 싶다면,
anim_save('population.gif')
다음은 + enter_fade()
를 사용한 것과 하지 않은 것의 차이를 보여준다.
한국의 인구구조 변천사(1960-2020)
이렇게 보니 정말 애들이 없네요!
Leave a comment