drawing pyramid plot using R and ggplot2

后端 未结 5 1658
感动是毒
感动是毒 2020-11-29 00:43

I need to draw a pyramid plot, like the one attached.

\"alt

I found an example using R (but not

5条回答
  •  一向
    一向 (楼主)
    2020-11-29 01:14

    This is essentially a back-to-back barplot, something like the ones generated using ggplot2 in the excellent learnr blog: http://learnr.wordpress.com/2009/09/24/ggplot2-back-to-back-bar-charts/

    You can use coord_flip with one of those plots, but I'm not sure how you get it to share the y-axis labels between the two plots like what you have above. The code below should get you close enough to the original:

    First create a sample data frame of data, convert the Age column to a factor with the required break-points:

    require(ggplot2)
    df <- data.frame(Type = sample(c('Male', 'Female', 'Female'), 1000, replace=TRUE),
                     Age = sample(18:60, 1000, replace=TRUE))
    
    AgesFactor <- ordered( cut(df$Age, breaks = c(18,seq(20,60,5)), 
                               include.lowest = TRUE))
    
    df$Age <- AgesFactor
    

    Now start building the plot: create the male and female plots with the corresponding subset of the data, suppressing legends, etc.

    gg <- ggplot(data = df, aes(x=Age))
    
    gg.male <- gg + 
      geom_bar( subset = .(Type == 'Male'), 
                aes( y = ..count../sum(..count..), fill = Age)) +
      scale_y_continuous('', formatter = 'percent') + 
      opts(legend.position = 'none') +
      opts(axis.text.y = theme_blank(), axis.title.y = theme_blank()) + 
      opts(title = 'Male', plot.title = theme_text( size = 10) ) +  
      coord_flip()    
    

    For the female plot, reverse the 'Percent' axis using trans = "reverse"...

    gg.female <- gg + 
      geom_bar( subset = .(Type == 'Female'), 
                aes( y = ..count../sum(..count..), fill = Age)) +
      scale_y_continuous('', formatter = 'percent', trans = 'reverse') + 
      opts(legend.position = 'none') +
      opts(axis.text.y = theme_blank(), 
           axis.title.y = theme_blank(), 
           title = 'Female') +
      opts( plot.title = theme_text( size = 10) ) +
      coord_flip()
    

    Now create a plot just to display the age-brackets using geom_text, but also use a dummy geom_bar to ensure that the scaling of the "age" axis in this plot is identical to those in the male and female plots:

    gg.ages <- gg + 
      geom_bar( subset = .(Type == 'Male'), aes( y = 0, fill = alpha('white',0))) +
      geom_text( aes( y = 0,  label = as.character(Age)), size = 3) +
      coord_flip() +
      opts(title = 'Ages',
           legend.position = 'none' ,
           axis.text.y = theme_blank(),
           axis.title.y = theme_blank(),
           axis.text.x = theme_blank(),
           axis.ticks = theme_blank(),          
           plot.title = theme_text( size = 10))       
    

    Finally, arrange the plots on a grid, using the method in Hadley Wickham's book:

    grid.newpage()
    
    pushViewport( viewport( layout = grid.layout(1,3, widths = c(.4,.2,.4))))
    
    vplayout <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
    
    print(gg.female, vp = vplayout(1,1))
    print(gg.ages,   vp = vplayout(1,2))
    print(gg.male,   vp = vplayout(1,3))
    

    alt text

提交回复
热议问题