人口金字塔圖是描述一個地區(qū)或國家人口結(jié)構(gòu)類型的常用圖示方式,今天我們介紹一下如何利用R語言制作金字塔圖找岖,快來看看如何作金字塔圖吧拨脉!
什么是人口金字塔圖?
人口金字塔是用類似古埃及金字塔的形象描繪人口年齡和性別分布狀況的圖形宣增。能表明人口現(xiàn)狀及其發(fā)展類型玫膀,比如看一個地區(qū)或國家的人口結(jié)構(gòu)類型是擴展型、穩(wěn)定型或者收縮型爹脾。
圖形的畫法是:按男女人口年齡自然順序自下而上在縱軸左右畫成并列的橫條柱帖旨,各條柱代表各個年齡組。底端標有按一定計算單位或百分比表示的人口數(shù)量灵妨。
下面我們介紹一下如何利用R畫出人口金字塔圖解阅。
用到哪些R包?
今天主要用到 dplyr包泌霍、reshape2包货抄、ggplot2包和cowplot包。 dplyr包和reshape2包用來進行數(shù)據(jù)整理朱转,ggplot2包和cowplot包用來畫圖和整合蟹地。
加載這些R包
library(dplyr)
##
## 載入程輯包:'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(reshape2)
library(ggplot2)
library(cowplot)
數(shù)據(jù)處理
首先需要把我們手里的現(xiàn)有數(shù)據(jù)讀取到R工作環(huán)境,然后把數(shù)據(jù)調(diào)整為ggplot2包繪圖所需要的格式藤为。
我們看一下怪与,我們目前的數(shù)據(jù)結(jié)構(gòu)和變量基本信息吧,目前我們有一個數(shù)據(jù)框缅疟,數(shù)據(jù)框里有20列數(shù)據(jù)分别,第一列為性別(sex),其余分別為0遍愿,1,4~耘斩,...沼填,85+歲組各年齡組的人口數(shù)據(jù)。
pop <- read.csv("pop.csv")
pop <- pop %>%
#把合計人口數(shù)去掉只保留男性和女性人口
filter(sex %in% c("男性","女性"))
head(pop)
## sex r0 r1 r5 r10 r15 r20 r25 r30 r35
## 1 男性 193565 924420 1186130 1158427 1130776 1254271 1426065 1291455 1279639
## 2 女性 176068 821772 1038768 991518 1002524 1162174 1365563 1235362 1208151
## r40 r45 r50 r55 r60 r65 r70 r75 r80 r85
## 1 1322747 1338809 1145094 941395 812746 622679 440440 300147 183825 102596
## 2 1261624 1292094 1101333 918208 801106 635924 467743 342476 228937 164663
但是括授,ggplot2繪圖需要讀取縱向格式的數(shù)據(jù)倾哺,也就是說我們需要把目前的數(shù)據(jù)格式轉(zhuǎn)換成兩列,一列為性別刽脖,另一列為人口數(shù)羞海。因此,我們需要把目前的數(shù)據(jù)轉(zhuǎn)換成縱向結(jié)構(gòu)數(shù)據(jù)曲管。
reshape2包的melt函數(shù)可以把橫向數(shù)據(jù)轉(zhuǎn)換為縱向數(shù)據(jù)却邓,id.vars參數(shù)指定保留的變量名稱,其余的變量都轉(zhuǎn)職置為縱向結(jié)構(gòu)院水,轉(zhuǎn)換為兩列腊徙,一列存放變量名,一列存放變量值檬某。variable.name指定存放變量名的那一列的變量名撬腾,value.name指定存放變量值的那一列的變量名。
# 對橫向數(shù)據(jù)進行轉(zhuǎn)置恢恼,然后存入pop數(shù)據(jù)框
pop <- pop %>%
# reshape2包的melt函數(shù)轉(zhuǎn)置橫向數(shù)據(jù)
melt(id.vars=c("sex"),
variable.name="age",
value.name = "pop")
現(xiàn)在來看看轉(zhuǎn)置后的數(shù)據(jù)吧
head(pop)
## sex age pop
## 1 男性 r0 193565
## 2 女性 r0 176068
## 3 男性 r1 924420
## 4 女性 r1 821772
## 5 男性 r5 1186130
## 6 女性 r5 1038768
然后把目前pop數(shù)據(jù)框的age變量值進行轉(zhuǎn)換民傻,因為它的值就是人口金字塔中顯示的年齡組的值。
pop<-pop%>%
mutate(age=as.numeric(gsub("r","",age)),
pop=ifelse(sex=="男性",-pop,pop))
繪制人口金字塔的時候场斑,橫條的長度采用跟年齡組人口數(shù)占相應(yīng)人口的百分比來表示漓踢,因此計算人口百分比數(shù)據(jù)。
age_label<- c("0","1-4","5-9","10-14","15-19","20-24","25-29","30-34","35-39","40-44","45-49","50-54","55-59","60-64","65-69","70-74","75-79","80-84","85-")
pop <- pop%>%
group_by(sex)%>%
mutate(pop_rate=pop/sum(pop)*100)%>%
mutate(pop_rate=ifelse(sex=="男性",-pop_rate,pop_rate))
然后把人口數(shù)據(jù)拆分成男性和女性兩個數(shù)據(jù)框漏隐,并把這個兩個數(shù)據(jù)框存入列表ct
ct <- pop%>%group_by(sex)%>%group_split()
ct
## <list_of<
## tbl_df<
## sex : character
## age : double
## pop : integer
## pop_rate: double
## >
## >[2]>
## [[1]]
## # A tibble: 19 x 4
## sex age pop pop_rate
## <chr> <dbl> <int> <dbl>
## 1 男性 0 -193565 -1.13
## 2 男性 1 -924420 -5.42
## 3 男性 5 -1186130 -6.95
## 4 男性 10 -1158427 -6.79
## 5 男性 15 -1130776 -6.63
## 6 男性 20 -1254271 -7.35
## 7 男性 25 -1426065 -8.36
## 8 男性 30 -1291455 -7.57
## 9 男性 35 -1279639 -7.50
## 10 男性 40 -1322747 -7.76
## 11 男性 45 -1338809 -7.85
## 12 男性 50 -1145094 -6.71
## 13 男性 55 -941395 -5.52
## 14 男性 60 -812746 -4.77
## 15 男性 65 -622679 -3.65
## 16 男性 70 -440440 -2.58
## 17 男性 75 -300147 -1.76
## 18 男性 80 -183825 -1.08
## 19 男性 85 -102596 -0.602
##
## [[2]]
## # A tibble: 19 x 4
## sex age pop pop_rate
## <chr> <dbl> <int> <dbl>
## 1 女性 0 176068 1.09
## 2 女性 1 821772 5.07
## 3 女性 5 1038768 6.41
## 4 女性 10 991518 6.11
## 5 女性 15 1002524 6.18
## 6 女性 20 1162174 7.17
## 7 女性 25 1365563 8.42
## 8 女性 30 1235362 7.62
## 9 女性 35 1208151 7.45
## 10 女性 40 1261624 7.78
## 11 女性 45 1292094 7.97
## 12 女性 50 1101333 6.79
## 13 女性 55 918208 5.66
## 14 女性 60 801106 4.94
## 15 女性 65 635924 3.92
## 16 女性 70 467743 2.88
## 17 女性 75 342476 2.11
## 18 女性 80 228937 1.41
## 19 女性 85 164663 1.02
為了使用方便喧半,我們編制一個函數(shù),并利用lapply函數(shù)把ct列表放入進去青责,這樣就可以自動生成橫向條形圖挺据。
制作金字塔圖的思路
我們先編寫一個函數(shù),實現(xiàn)對列表數(shù)據(jù)進行處理脖隶,判斷如果是男性數(shù)據(jù)的話則生成左側(cè)橫向條形圖扁耐,如果是女性數(shù)據(jù)的話則生成右側(cè)橫向條形圖,然后把利用cowplot把左側(cè)條形圖和右側(cè)條形圖組成一個金字塔圖浩村。
上程序:
# top_value <- max(abs(pop$pop_rate))
p<- lapply(ct,function(x) {
sexx <- x[1,c("sex")]
abslabel <- function(x) {paste(abs(x),"%",sep="")}
mycolor <- ifelse(sexx=="男性",paste("steelblue"),paste("red"))
pp<-ggplot(x) +
geom_bar(aes(x=pop_rate,y=factor(age,labels=age_label)), stat = "identity",color="white",width=0.9,fill=ifelse(x$pop_rate>0,'#e31a1c','#1f78b4'))+
scale_x_continuous(expand = expansion(),limits=c(0,9.9),labels=abslabel)+
xlab(ifelse(sexx=="男性","男性","女性"))+
theme_void()+
theme(
axis.title.y = element_blank(),
panel.border = element_blank(),
panel.grid=element_blank(),
panel.grid.major =element_blank(),
axis.ticks.y = element_blank(),
axis.line.y=element_blank(),
axis.text.x = element_text(face="bold"),
axis.text.y =element_text(size=12),
axis.title.x=element_text(size=12)
)
if (sexx=="男性"){ pp<- pp+ theme(axis.text.y =element_blank())+scale_x_continuous(expand = expansion(),limits=c(-9.9,0),labels=abslabel)
}
return(pp)
})
上面的程序有已經(jīng)把生成的左側(cè)和右側(cè)條形圖放入列表p做葵,下面把列表的第一個元素和第二個元素利用cowplot組合起來就是一個金字塔圖了。
# 利用plot_grid來組合p列表元素心墅,進行橫向拼接酿矢,存入pyramid
pyramid <- plot_grid(p[[1]],p[[2]],ncol=2,align="hv")
我們來看看最終的金字塔圖的吧。
pyramid
小結(jié)
本篇文章介紹了如何利用R語言制作人口金字塔圖怎燥,利用本程序的思路瘫筐,稍微修改,可以批量制作金字塔圖铐姚。