R ggplot2中更简单的人口金字塔

R ggplot2中更简单的人口金字塔,r,ggplot2,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) test这里是一个没有刻面的解决方案。首先,创建数据帧。我使用了从1到20的

我想用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)

test这里是一个没有刻面的解决方案。首先,创建数据帧。我使用了从1到20的值来确保没有一个值是负的(使用人口金字塔,您不会得到负计数/年龄)

更新 由于参数
subset=。
在最新的
ggplot2
版本中被弃用,因此可以使用函数
subset()
查看相同的结果


人口金字塔的通用ggplot代码模板(如下所示)

  • 使用
    geom_col()
    而不是
    geom_bar()
    ,后者具有更好的默认值
    stat
    ,并且避免了
    coord_flip()
  • 通过在缩放功能中使用
    labels=abs
    避免手动设置标签分隔符
  • 具有相等的男性和女性水平轴(和标签),以便于性别之间的比较-使用lemon软件包中的
    scale\u x\u symmetric()
  • 仅使用一个geom,避免了数据子集的需要;如果要在镶嵌面打印中创建多个棱锥体,这非常有用
  • 正在创建数据

    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
    

    扩展@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
    

    popPy1我认为这更适合于前面关于同一主题的问题。有时人们不得不从
    ggplot2
    @dmvianna迁移,我是一个狂热的
    ggplot2
    用户,但当我最近不得不创建一个人口金字塔时,我最终放弃并使用了
    plotrix
    软件包中的
    pyramid.plot
    。这并不困难,结果完全可以被我的眼睛接受。坦白地说,这比使用
    ggplot
    或我自己使用
    ggplot
    的链接问题的结果要好得多。我得到了一个错误:“do.call(“layer”,list(mapping=mapping,data=data,stat=stat,:找不到函数”。“但是”+geom\bar(data=subset(test,g=“F”))'为我工作您可能需要使用
    library(plyr)
    cool plot显式加载
    plyr
    包。我收到一条警告:警告消息:In loop\u apply(n,do.ply):当ymin!=0时堆叠未定义好您知道它的含义吗?@ExpectoPatronum这是一个警告,因为我们在条形图中使用负值进行堆叠。发现错误“错误:未知参数:子集”在ggplot 2.1.0下。最好更新新版本的ggplot的答案。谢谢。在新版本的
    ggplot
    2.1.0下工作。这是一个简单的方法,效果相当好。应该是最重要的答案。干净、简单和可扩展-这太棒了!很好的
    lemon
    技巧!
    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()
    
    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
    
    library(ggplot2)
    library(lemon)
    
    ggplot(data = d, 
           mapping = aes(x = ifelse(test = sex == "Male", yes = -pop, no = pop), 
                         y = age, fill = sex)) +
      geom_col() +
      scale_x_symmetric(labels = abs) +
      labs(x = "Population")
    
    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