ggplot2中更简单的人口金字塔

dmv*_*nna 38 r 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)
Run Code Online (Sandbox Code Playgroud)

生成此图像.在我看来,这里创建人口金字塔的唯一步骤是反转第一个方面的x轴,使其从50变为0,同时保持第二个不变.有人可以帮忙吗?

人口金字塔

Did*_*rts 54

这是一个没有刻面的解决方案.首先,创建数据框架.我使用1到20之间的值来确保没有值是负数(人口金字塔没有得到负数/年龄).

test <- data.frame(v=sample(1:20,1000,replace=T), g=c('M','F'))
Run Code Online (Sandbox Code Playgroud)

然后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()
Run Code Online (Sandbox Code Playgroud)

UPDATE

由于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()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 我收到一个错误:'do.call中的错误("图层",列表(mapping = mapping,data = data,stat = stat,:找不到函数"."'但是'+ geom_bar(data = subset(test, g =="F"))'为我工作 (2认同)
  • 在ggplot 2.1.0下找到"错误:未知参数:子集"的错误.最好更新新版ggplot的答案.谢谢. (2认同)

gja*_*bel 26

一般的ggplot代码

  1. 避免一些摆弄水平轴上的标签断裂
  2. 避免geom_*()或需要额外的包装(例如plyr).如果要在构面图中创建多个金字塔,这可能特别有用.
  3. geom_col()仅使用一次,如果你想要的话,它会很有用.
  4. 雄性和雌性水平轴相等; geom_bar()正如人口统计学家常用的那样......如果不需要,可以删除代码中的行.

创建数据......

set.seed(100)
a <- seq(from = 0, to = 90, by = 10)
d <- data.frame(age = paste(a, a + 10, sep = "-"),
                sex = rep(x = c("Female", "Male"), each = 10),
                pop = sample(x = 1:100, size = 20))
head(d)
#     age    sex pop
# 1  0-10 Female  74
# 2 10-20 Female  89
# 3 20-30 Female  78
# 4 30-40 Female  23
# 5 40-50 Female  86
# 6 50-60 Female  70
Run Code Online (Sandbox Code Playgroud)

情节代码......

library(ggplot2)
ggplot(data = d, 
       mapping = aes(x = age, y = ifelse(test = sex == "Male", yes = -pop, no = pop), 
                     fill = sex)) +
    geom_col() +
    coord_flip() +
    scale_y_continuous(labels = abs, limits = max(d$pop) * c(-1,1)) +
    labs(y = "Population")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

请注意,如果您的数据是个人级别而不是按年龄 - 性别组进行汇总,那么此处的答案也非常普遍.

  • 干净、简单且可扩展——这太棒了! (4认同)
  • 这是一个简单的方法并且效果很好。应该是最上面的答案。 (3认同)
  • 在新版本的 `ggplot` 2.1.0 下工作。 (2认同)