Search code examples
rggplot2ggplotly

How to create percent stacked shape with ggplot


is there a way that I could do Percent stacked plot with ggplot2 geom_rect() layer? I have coordinates, so I create a shape, I also have my separation variable t, now I would like to fill the shape based on the occurrence of t. In other words, I would like to do Percent stacked barchart but instead of a barchart a custom shape (in my case, simple rectangles). I've been experimenting a lot with position="fill", stat="identity" and their varieties but without any success. I wonder if it possible and if so, how could I achieve it?

df <- structure(list(x1 = c(4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 
3, 3), x2 = c(6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 4), y1 = c(3, 
3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1), y2 = c(5, 5, 5, 5, 
5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2), t = structure(c(1L, 1L, 1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 1L), .Label = c("a", 
"b"), class = "factor")), row.names = c("1", "2", "3", "4", "5", 
"6", "7", "8", "9", "10", "11", "12", "13", "14", "15"), class = "data.frame")

library(ggplot2)
ggplot() + 
    geom_rect(data=d, mapping=aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2, fill = t))

expected result enter image description here

Thank you for your time!


Solution

  • Here is the working code for the desired plot, it took some coding using dplyr, but it worked.

    library(ggplot2)
    library(tidyverse)
    
    df1<-df %>%
      group_by(x1,y1,x2,y2,t) %>%
      count() %>% 
      ungroup() %>%
      group_by(x1,y1) %>%
      mutate(perc = n / sum(n),
             percLabel = paste(100 * perc,"%",sep = " "),
             transf = abs(x2-x1) * perc,
             newx1 = ifelse(t == "a", x1,x2-transf),
             newx2 = ifelse(t == "a", x1+transf,x2)) 
    
    
    ggplot(df1,aes(xmin = newx1, 
                   xmax = newx2, 
                   ymin = y1, 
                   ymax = y2, 
                   fill = t)) + 
      geom_rect(col = "black") + 
      geom_text(aes(x = newx1 + ((newx2 - newx1)/2), 
                                  y = y1 + ((y2 - y1)/2), 
                                  label = percLabel)) + 
      labs(x="X",y="Y")
    

    plot