ggplot2: facet_wrap strip color based on variable in data set

前端 未结 4 1813
余生分开走
余生分开走 2020-11-28 03:05

Is there a way to fill the strips of facets created with facet_wrap based on a variable supplied with the data frame?

Example data:

MYdata <- data.f

相关标签:
4条回答
  • 2020-11-28 03:32

    With a little bit of work, you can combine your plot with a dummy gtable that has the right grobs,

    enter image description here

    d <- data.frame(fruit = rep(c("apple", "orange", "plum", "banana", "pear", "grape")), 
                    farm = rep(c(0,1,3,6,9,12), each=6), 
                    weight = rnorm(36, 10000, 2500), 
                    size=rep(c("small", "large")))
    
    p1 = ggplot(data = d, aes(x = farm, y = weight)) + 
      geom_jitter(position = position_jitter(width = 0.3), 
                  aes(color = factor(farm)), size = 2.5, alpha = 1) + 
      facet_wrap(~fruit)
    
    dummy <- ggplot(data = d, aes(x = farm, y = weight))+ facet_wrap(~fruit) + 
      geom_rect(aes(fill=size), xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
      theme_minimal()
    
    library(gtable)
    
    g1 <- ggplotGrob(p1)
    g2 <- ggplotGrob(dummy)
    
    gtable_select <- function (x, ...) 
    {
      matches <- c(...)
      x$layout <- x$layout[matches, , drop = FALSE]
      x$grobs <- x$grobs[matches]
      x
    }
    
    panels <- grepl(pattern="panel", g2$layout$name)
    strips <- grepl(pattern="strip_t", g2$layout$name)
    g2$layout$t[panels] <- g2$layout$t[panels] - 1
    g2$layout$b[panels] <- g2$layout$b[panels] - 1
    
    new_strips <- gtable_select(g2, panels | strips)
    grid.newpage()
    grid.draw(new_strips)
    
    gtable_stack <- function(g1, g2){
      g1$grobs <- c(g1$grobs, g2$grobs)
      g1$layout <- transform(g1$layout, z= z-max(z), name="g2")
      g1$layout <- rbind(g1$layout, g2$layout)
      g1
    }
    ## ideally you'd remove the old strips, for now they're just covered
    new_plot <- gtable_stack(g1, new_strips)
    grid.newpage()
    grid.draw(new_plot)
    
    0 讨论(0)
  • 2020-11-28 03:33

    It's not directly for differently coloring your facets but here you have another (very quick and simpler) solution, based on facet by two variables (size ~ fruit) instead one (~ fruit):

    ggplot(data = MYdata, aes(x = farm, y = weight)) + 
      geom_jitter(position = position_jitter(width = 0.3), 
          aes(color = factor(farm)), size = 2.5, alpha = 1) + 
      facet_wrap(size ~ fruit)
    

    0 讨论(0)
  • 2020-11-28 03:34

    You can find an updated answer to this question here.

    g <- ggplot_gtable(ggplot_build(p))
    stripr <- which(grepl('strip-r', g$layout$name))
    fills <- c("red","green","blue","yellow")
    k <- 1
    for (i in stripr) {
      j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
      g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
      k <- k+1
    }
    grid::grid.draw(g)
    

    0 讨论(0)
  • 2020-11-28 03:51

    I would love to know how to do that, it is a great idea. One idea is to generate each chart independently with a different color as you do and then use something like multiplot or viewports to show then side by side - it will require a bit more work.

    if you want to extract the legend, which you will need for this approach - here is some code from Hadley that I found a while back

    g_legend<-function(a.gplot){
      tmp <- ggplot_gtable(ggplot_build(a.gplot))
      leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
      legend <- tmp$grobs[[leg]]
      return(legend)}
    

    see how it is extracted it from chart p, and then I took it out of the plot legend <- g_legend(p) lwidth <- sum(legend$width) #if you want to define the viewport based on this p <- p + theme(legend.position="none")

    then you eventually draw it

    grid.newpage()
    vp <- viewport(width = 1, height = 1)
    #print(p, vp = vp)
    
    submain <- viewport(width = 0.9, height = 0.9, x = 0.5, y = 1,just=c("center","top"))
    print(p, vp = submain)
    sublegend <- viewport(width = 0.5, height = 0.2, x = 0.5, y = 0.0,just=c("center","bottom"))
    print(arrangeGrob(legend), vp = sublegend)
    

    Good luck

    0 讨论(0)
提交回复
热议问题