이 글을 통하여 인터넷에서 세계 각국의 census 자료를 구하는 방법을 배우고 다음과 같은 인구 피라미드를 그려보고자 한다.
US Census Bereau (미국 인구통계청(?))에 접속해 보면 미국 뿐 아니라 우리나라를 포함한 세계 각국의 인구통계자료를 얻을 수 있다.
http://www.census.gov/population/international/data/idb/informationGateway.php
이 부분은 rpubs.com에 있는 Kyle Walker의 자료를 참고로 하였음을 밝힌다.(https://rpubs.com/walkerke/pyramids_ggplot2)
이 곳에서 각 나라별/년도별로 인구 구성자료를 얻는 명령어는 다음과 같다.
require(XML)
require(reshape2)
require(ggplot2)
require(plyr)
get_popdata <- function(country, year) {
c1 <- "http://www.census.gov/population/international/data/idb/region.php?N=%20Results%20&T=10&A=separate&RT=0&Y="
c2 <- "&R=-1&C="
url <- paste0(c1, year, c2, country)
df <- data.frame(readHTMLTable(url))
keep <- c(2, 4, 5)
df <- df[,keep]
names(df) <- c("Age", "Male", "Female")
cols <- 2:3
df[,cols] <- apply(df[,cols], 2, function(x) as.numeric(as.character(gsub(",", "", x))))
df <- df[df$Age != 'Total', ]
df
}
각 나라의 코드는 FIPS 10-4 country code를 입력하면 된다. 한국의 2016년 자료는 다음과 같이 얻을 수 있다.
KS2016 <- get_popdata("KS",2016)
KS2016
Age Male Female
2 0-4 1045502 980744
3 5-9 1114906 1040784
4 10-14 1228881 1127233
5 15-19 1632827 1480361
6 20-24 1839108 1612022
7 25-29 1643682 1465633
8 30-34 1875413 1684496
9 35-39 2030163 1858761
10 40-44 1947419 1976000
11 45-49 2105234 2072716
12 50-54 1984425 2024234
13 55-59 1960692 1978623
14 60-64 1425861 1483515
15 65-69 987232 1099192
16 70-74 733879 915130
17 75-79 558581 816824
18 80-84 312740 560019
19 85-89 109768 283745
20 90-94 32466 113070
21 95-99 5664 28305
22 100+ 537 4389
이 자료를 이용하여 인구피라미드를 그리려면 다음 순서에 따른다.
남자의 자료를 음수로 만들고 long form으로 변환한다.
KS2016$Male <- -1 * KS2016$Male
KS2016$Age <- factor(KS2016$Age,levels=KS2016$Age)
longdf <- melt(KS2016,id.vars="Age",value.name="Population",variable.name="Gender")
head(longdf)
Age Gender Population
1 0-4 Male -1045502
2 5-9 Male -1114906
3 10-14 Male -1228881
4 15-19 Male -1632827
5 20-24 Male -1839108
6 25-29 Male -1643682
ggplot2를 이용하여 그림을 그린다. geom_bar()를 두번 호출한다.
p <- ggplot(data=longdf,aes(x=Age,y=Population,fill=Gender))+
geom_bar(data=subset(longdf, Gender == "Male"), stat = "identity") +
geom_bar(data=subset(longdf, Gender == "Female"), stat = "identity")
p
x축과 y축을 뒤바꾼다.
p<- p+coord_flip()
p
인구수 format 이 scientific exponent format으로 되어 있다. 이를 천단위, 백만단위, 십억단위로 바꾸려면 다음과 같이 할 수 있다.
이 부분은 fdryan의 github에 있는 코드를 조금 변형하였다.
require(scales)
human_numbers <- function(x = NULL, smbl ="", allpos = FALSE){
humanity <- function(y){
if (!is.na(y)){
b <- round_any(abs(y) / 1e9, 0.1)
m <- round_any(abs(y) / 1e6, 0.1)
k <- round_any(abs(y) / 1e3, 0.1)
if ( y >= 0 ){
y_is_positive <- ""
} else {
y_is_positive <- "-"
}
if(allpos) y_is_positive <- ""
if ( k < 1 ) {
paste0(y_is_positive, smbl, y )
} else if ( m < 1){
paste0 (y_is_positive, smbl, k , "k")
} else if (b < 1){
paste0 (y_is_positive, smbl, m ,"m")
} else {
paste0 (y_is_positive, smbl, comma(b), "b")
}
}
}
sapply(x,humanity)
}
#' Human versions of large currency numbers - extensible via smbl
human_gbp <- function(x){human_numbers(x, smbl = "£")}
human_usd <- function(x){human_numbers(x, smbl = "$")}
human_euro <- function(x){human_numbers(x, smbl = "€")}
human_num <- function(x){human_numbers(x, smbl = "")}
human_num2 <- function(x){human_numbers(x, smbl = "",allpos=TRUE)}
wide form의 자료를 이용하여 Bidirectional barplot을 그려주는 함수를 만들어 보았다. 내부적으로 자료를 long form으로 바꾸어 주고 그래프를 그려준다. ggBidirectionalBar() 함수는 웹R에 공개되어 있다.
다음과 같이 사용하면 된다. 일본의 인구구성을 보자.
JA2016=get_popdata("JA",2016)
ggBidirectionalBar(data=JA2016,left="Male",right="Female",label="Age")
mode를 0으로 하면 인구군이 가운데에 들어간다.
ggBidirectionalBar(data=JA2016,left="Male",right="Female",label="Age",mode=0)
인터넷에서 자료를 읽어오는 과정 및 그림그리는 과정을 모두 자동화 하는 함수를 만들어 보았다.
PopPyramid=function(country,year,mode=1){
popdata=get_popdata(country,year)
ggBidirectionalBar(data=popdata,left="Male",right="Female",label="Age",mode=mode,
title=paste("Population",country,year))
}
다음과 같이 사용하면 된다. 북한의 인구는 다음과 같다.
PopPyramid("KN",2016,mode=0)
나이지리아의 인구구조는 전형적인 피라미드이다
PopPyramid("NI",2016)
인구가 적은 United States Virgin Island섬의 인구구성이다.
PopPyramid("VQ",2016)