Home > Enterprise >  Add border / ring around pie chart as a sub-proportion based on column value
Add border / ring around pie chart as a sub-proportion based on column value

Time:06-08

I have a dataframe sush as ;

tab

  Groups Cat1 Cat2
1      A    4    2
2      B    0    0
3      C    1    1
4      D    2    0

and from that dataframe I can manage to write the following plot :

ggplot(tab, aes(x=factor(1), y=factor(Cat1),fill=factor(Cat1)))  
  geom_bar(stat='identity',colour="white",size=0.7,width=1)  
  coord_polar(theta='y')   theme_inset()  theme(legend.position = c(0.10, 0.8))

enter image description here

I wondered if it was possible to also include the Cat2 column values by adding proportion black borders around each Groups Areas.

In such plot, I should get something like

As you can see, since 2/4 (50%) Cat2 are present for groupA, I only color half of the border around groupA, and since 1/1 (100%) Cat2 are present for groupC, I color all of the border around groupC. And since GroupD had 0 number in Cat2, it did not color the border at all.

enter image description here

Here is the dput format of the tabe if it can helps:

structure(list(Groups = c("A", "B", "C", "D"), Cat1 = c(4L, 0L, 
1L, 2L), Cat2 = c(2L, 0L, 1L, 0L)), class = "data.frame", row.names = c(NA, 
-4L))

CodePudding user response:

One option to achieve your desired result would be to first create a second dataframe which also includes the number of Non-"Category 2" Values. This second dataframe could then be used to draw a donut around your pie chart where I use "transparent" color to fill the Non-Cat2 category.

To make this work we have to add a new grouping column as the interaction of your Groups column and the new Cat2/Non-Cat2 column. Also I switched to a continuous x scale which makes it easy to "wrap" the donut nicely around the pie.

library(ggplot2)
library(dplyr)
library(tidyr)

tab1 <- tab |> 
  mutate(nonCat2 = Cat1 - Cat2) |> 
  pivot_longer(c(Cat2, nonCat2), names_to = "Groups1", values_to = "Cat2") |>
  mutate(Groups = interaction(Groups, Groups1, lex.order = TRUE))

pal <- scales::hue_pal()(4)
names(pal) <- c("A", "B", "C", "D")
pal <- c(pal, c(Cat2 = "black", nonCat2 = "transparent"))

ggplot()  
  geom_col(data = tab, aes(x = 1, y = Cat1, fill = Groups), color = "white")  
  geom_col(data = tab1, aes(x = 1.5, y = Cat2, fill = Groups1, group = Groups), width = .1, color = "white")  
  scale_fill_manual(values = pal, breaks = LETTERS[1:4])  
  coord_polar(theta = "y")  
  theme_void()  
  theme(legend.position = c(0.10, 0.8))

enter image description here

  • Related