Упрощенная пирамида населения в ggplot2
Я хочу создать пирамиду населения с помощью ggplot2. Этот вопрос задавался до, но я считаю, что решение должно быть намного проще.
test <- (data.frame(v=rnorm(1000), g=c('M','F')))
require(ggplot2)
ggplot(data=test, aes(x=v)) +
geom_histogram() +
coord_flip() +
facet_grid(. ~ g)
Создает это изображение. На мой взгляд, единственный шаг, отсутствующий здесь для создания пирамиды населения, состоит в том, чтобы инвертировать ось x первой грани, так что она идет от 50 до 0, сохраняя при этом вторую нетронутую. Может ли кто-нибудь помочь?
![Population pyramid]()
Ответы
Ответ 1
Вот решение без огранки. Сначала создайте фрейм данных. Я использовал значения от 1 до 20, чтобы гарантировать, что ни одно из значений не будет отрицательным (с пирамидами населения вы не получите отрицательных значений/возрастов).
test <- data.frame(v=sample(1:20,1000,replace=T), g=c('M','F'))
Затем комбинируются два geom_bar()
вызова отдельно для каждого из значений g
. Для F
подсчеты рассчитываются так, как они есть, но для M
количество отсчетов умножается на -1, чтобы получить бар в противоположном направлении. Затем scale_y_continuous()
используется для получения хороших значений для оси.
require(ggplot2)
require(plyr)
ggplot(data=test,aes(x=as.factor(v),fill=g)) +
geom_bar(subset=.(g=="F")) +
geom_bar(subset=.(g=="M"),aes(y=..count..*(-1))) +
scale_y_continuous(breaks=seq(-40,40,10),labels=abs(seq(-40,40,10))) +
coord_flip()
ОБНОВЛЕНИЕ
Поскольку аргумент subset=.
устарел в последних версиях ggplot2
, тот же результат может быть получен с помощью функции subset()
.
ggplot(data=test,aes(x=as.factor(v),fill=g)) +
geom_bar(data=subset(test,g=="F")) +
geom_bar(data=subset(test,g=="M"),aes(y=..count..*(-1))) +
scale_y_continuous(breaks=seq(-40,40,10),labels=abs(seq(-40,40,10))) +
coord_flip()
![enter image description here]()
Ответ 2
Общий код ggplot, который
- Предотвращает некоторую суету вокруг разрывов надписей на горизонтальной оси
- Избегает
subset
или необходимости дополнительных пакетов (например, plyr). Это может быть особенно полезно, если вы хотите создать несколько пирамид на фасетном графике.
- Использует
geom_bar()
только один раз, что полезно, если вы хотите получить фасет.
- Имеет равные мужские и женские горизонтальные оси;
limits = max(df0$Population) * c(-1,1)
, как обычно используют демографы... удалите, если не требуется.
Создание данных...
set.seed(1)
df0 <- data.frame(Age = factor(rep(x = 1:10, times = 2)),
Gender = rep(x = c("Female", "Male"), each = 10),
Population = sample(x = 1:100, size = 20))
head(df0)
# Age Gender Population
# 1 1 Female 27
# 2 2 Female 37
# 3 3 Female 57
# 4 4 Female 89
# 5 5 Female 20
# 6 6 Female 86
Код участка...
library(ggplot2)
ggplot(data = df0,
mapping = aes(x = Age,
y = ifelse(test = Gender == "Male", yes = -Population, no = Population),
fill = Gender)) +
geom_bar(stat = "identity") +
scale_y_continuous(labels = abs, limits = max(df0$Population) * c(-1,1)) +
labs(y = "Population") +
coord_flip()
![enter image description here]()
Обратите внимание, что если ваши данные представлены на индивидуальном уровне, а не суммированы по возрасту и полу, то ответ здесь также довольно обобщенный.
Ответ 3
Расширяя пост @gjabel, мы видим чистую популяционную пирамиду, опять же, просто используя ggplot2.
popPy1 <- ggplot(data = venDemo,
mapping = aes(
x = AgeName,
y = ifelse(test = sex == "M", yes = -Percent, no = Percent),
fill = Sex2,
label=paste(round(Percent*100, 0), "%", sep="")
)) +
geom_bar(stat = "identity") +
#geom_text( aes(label = TotalCount, TotalCount = TotalCount + 0.05)) +
geom_text(hjust=ifelse(test = venDemo$sex == "M", yes = 1.1, no = -0.1), size=6, colour="#505050") +
# scale_y_continuous(limits=c(0,max(appArr$Count)*1.7)) +
# The 1.1 at the end is a buffer so there is space for the labels on each side
scale_y_continuous(labels = abs, limits = max(venDemo$Percent) * c(-1,1) * 1.1) +
# Custom colours
scale_fill_manual(values=as.vector(c("#d23f67","#505050"))) +
# Remove the axis labels and the fill label from the legend - these are unnecessary for a Population Pyramid
labs(
x = "",
y = "",
fill="",
family=fontsForCharts
) +
theme_minimal(base_family=fontsForCharts, base_size=20) +
coord_flip() +
# Remove the grid and the scale
theme(
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_text(family=fontsForCharts, size=20),
strip.text.x=element_text(family=fontsForCharts, size=24),
legend.position="bottom",
legend.text=element_text(size=20)
)
popPy1
![Population Pyramid]()