-
Notifications
You must be signed in to change notification settings - Fork 2
/
ACS-age-pyramids.R
119 lines (83 loc) · 3.84 KB
/
ACS-age-pyramids.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#########################################################################
# Carl Schmertmann
# 13 Jan 2019
#
# Age/Sex distribution of all counties in a chosen US state
# ACS 2012-2016 data
# using 'acs' and 'ggplot' packages
#########################################################################
library(acs)
library(tidyverse)
my_state = 'FL'
acs_end_year = 2017
# these colors are supposedly colorblind-friendly and printable
female_color = '#fc8d59'
male_color = '#91bfdb'
## You must have your own api key: get it from
## https://api.census.gov/data/key_signup.html
##
## Once you have a key, just change the command below
## to something like
## api.key.install( 'hfdsjku978dfsks...' ) with your own key in quotes
api.key.install( scan('api_key.txt',what='character') )
## set up the 'geo.set' object that the ACS package uses to select
## counties in your state as the geography of interest
## Note that you could change county= to other political geographies
G = geo.make(state=my_state, county = '*')
## fetch the age-sex distribution of each location
## (table B01001, according to the documentation at
## http://www2.census.gov/programs-surveys/acs/summary_file/2012/documentation/5_year/user_tools/ACS2012_5-Year_TableShells.xls )
A = acs.fetch( endyear=acs_end_year, span=5,
geography=G, table.number = 'B01001',
col.names='pretty')
## keep only the estimates
A = A@estimate
## put counties in alphabetical order
A = A[ order(rownames(A)), ]
## the data in A includes some double-counting of population, and several five-year
## age groups are split.
# for each of column of A, identify which sex/five-year age group it belongs to (NA = none)
group = c( rep(NA,2), 'M00','M05','M10',rep('M15',2),rep('M20',3),'M25','M30','M35','M40','M45',
'M50','M55', rep('M60',2), rep('M65',2), 'M70','M75','M80','M85',
NA, 'F00','F05','F10',rep('F15',2),rep('F20',3),'F25','F30','F35','F40','F45',
'F50','F55', rep('F60',2), rep('F65',2), 'F70','F75','F80','F85')
age_group_label = c('0-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+')
# aggregate populations into sex x five-year age groups for each row of A
pop = t( apply(A, 1, function(x) tapply(x,group,sum)) )
# plot the age pyramids
# convert the population data from matrix -> (long) data.frame
state_data = expand.grid( loc=rownames(pop),
age=seq(0,85,5),
sex=c('Female','Male'),
stringsAsFactors = FALSE)
# add the population as a final column
state_data$pop = as.vector(pop)
# change the sign of the male pops
state_data = mutate(state_data, pop = pop * ifelse(sex=='Male', -1, +1))
locations = unique(state_data$loc)
# reset graphics
graphics.off()
pdf(file=paste0('ACS-age-pyramids-', my_state ,'.pdf')) # open pdf
## draw the age pyramid for each location:
## this is based on Kyle Walker's code
for (i in locations) {
this_loc = filter(state_data,loc==i)
pyramid = ggplot(this_loc,
aes(x = age, y = pop, fill = sex)) +
geom_bar(data=filter(this_loc,sex == "Female"), stat = "identity") +
geom_bar(data=filter(this_loc,sex == "Male") , stat = "identity") +
scale_y_continuous(labels = abs) +
scale_x_continuous(breaks=seq(0,85,5),
labels=age_group_label) +
labs(y='Population', x='Age Group',
title=i, fill='',
caption=paste0('Source: American Community Survey ',
acs_end_year-4,'-',acs_end_year)) +
coord_flip() +
scale_fill_manual(values=c(female_color, male_color)) +
theme_bw()
print( pyramid )
} # for i
dev.off() # close pdf