인구피라미드 : Bidirectional Barplot
문건웅
2016년 5월 22일
목표
이 글을 통하여 인터넷에서 세계 각국의 census 자료를 구하는 방법을 배우고 다음과 같은 인구 피라미드를 그려보고자 한다.
이 글을 통하여 인터넷에서 세계 각국의 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
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
양방향 barplot 그리기
이 자료를 이용하여 인구피라미드를 그리려면 다음 순서에 따른다.
- 먼저 왼쪽 방향 barplot 으로 그릴 자료(남자)는 음수로 만들고
- 데이터를 long form으로 바꾸어 주어야 하며
- geom_bar()함수 를 이용하여 남자, 여자의 barplot을 그린 후
- coord_flip()함수로 수평 barplot으로 바꾸어주면 된다.
이 자료를 이용하여 인구피라미드를 그리려면 다음 순서에 따른다.
- 먼저 왼쪽 방향 barplot 으로 그릴 자료(남자)는 음수로 만들고
- 데이터를 long form으로 바꾸어 주어야 하며
- geom_bar()함수 를 이용하여 남자, 여자의 barplot을 그린 후
- coord_flip()함수로 수평 barplot으로 바꾸어주면 된다.
자료의 전처리
남자의 자료를 음수로 만들고 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
남자의 자료를 음수로 만들고 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
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
x축의 인구수 format
인구수 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)}
인구수 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)}
자동화된 함수의 제작
Bidirectional barplot
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)
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)
인터넷에서 자료를 읽어오는 과정 및 그림그리는 과정을 모두 자동화 하는 함수를 만들어 보았다.
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)
Comment 0
- Total
- 의학논문 작성을 위한 R통계와 그래프
- R을 이용한 조건부과정분석
- 웹에서 클릭만으로 하는 R통계분석
- Learn ggplot2 Using Shiny App
- 일반화가법모형 소개
- 밑바닥부터 시작하는 ROC 커브 분석
- 웹R을 이용한 통계분석
- 의료인을 위한 R 생존분석
No. | Subject | Author | Date |
---|---|---|---|
25 | 2판 출판 예정일 문의 [2] | pslee | 2024.01.23 |
24 | 2판 혹시 언제쯤 출간 예정일지요? [1] | 니콜라오 | 2023.10.13 |
23 | 2판 [1] | rlagurrn | 2023.01.27 |
22 | mytable 문의 [2] | 떠도는고라니 | 2022.12.20 |
21 | 제2판 출간소식을 기다립니다.. [1] | swpapa | 2021.04.05 |
20 | 책 구매 하려고 하는데 품절이 되서 구매할수 있는지 궁금합니다. [1] | 기드온 | 2020.07.30 |
19 | 메타분석 강의록 | cardiomoon | 2020.05.31 |
18 | 설문조사데이터 | cardiomoon | 2020.05.08 |
17 | 데이터 전처리 예제 | cardiomoon | 2020.05.08 |
16 | moonbook package 설치에 문제가 있는 건가요? [2] | KCRS_LeeJM | 2017.03.14 |
15 | 해결되지 않는 레이텍, ztable, moonbook2에 대해 질문 드립니다. [1] | neurojang | 2017.01.04 |
14 | Interactive plot with ggplot2 and ggiraph [1] | cardiomoon | 2016.05.25 |
13 | ggBidirectionalBar.R | cardiomoon | 2016.05.22 |
» | 인구피라미드 : Bidirectional Barplot | cardiomoon | 2016.05.22 |
11 | Radar Chart | cardiomoon | 2016.05.20 |
10 | ggRadar.R | cardiomoon | 2016.05.20 |
9 | Rose plot with ggplot2 [1] | cardiomoon | 2016.05.10 |
8 | Pie plot과 Donut plot의 결합 [2] | cardiomoon | 2016.05.08 |
7 | 책에 있는 R code 만 추출한 R 파일입니다. [1] | cardiomoon | 2016.05.03 |
6 | 교재 예제자료 [2] | 통계마술사 | 2016.01.18 |