0
votes

After looking at various post and asking questions here i have been able to make a multi faceted pie chart. But i am facing a problem in tidying up the pie chart. Here are the things i am having troubles with:

  1. How do i remove the facet labels from each row and only have one facet label on the top or bottom and left or right? How do i control how the facet label looks?
  • I have tried using facet_grid instead of facet_wrap and that removes the label from each row but still the labels are inside a box. I would like to remove the box which i donot seem to be able to do.
  1. Centering the labels so that the values for each fraction of the pie is inside that pie-slice. Some of my piechart have 8 to 10 values and they are not always inside there fraction. First i used geom_text_repel but that only helped me to repel the text. It didnt place the text inside each fraction. I also looked at this thread. I tried that by creating a new dataframe which has a position values and using that pos inside geom_text like so d<-c %>% group_by(Parameter)%>% mutate(pos= ave(Values, Zones, FUN = function(x) cumsum(x) - 0.5 * x)) and using the same code to make pie chart for d dataframe but it didnt quite work.
  2. Grouping the values under certain level into one single "other" groups so the number of slices would be less It would be ideal for me to be able to group the values with less than 1 % into one single group and call it "others" so that the number of slices are less. So far i have to completely ignore those values by c<-c[c$Values>1,] and using this newly created data frame.

Any suggestions/help regarding these issues would be helpful. Following is the reproducible example of my current pie chart:

library(RColorBrewer)
library(ggrepel)
library(ggplot2)
library(tidyverse)
my_pal <- colorRampPalette(brewer.pal(9, "Set1"))

#### create new matrix ############
new_mat<-matrix(, nrow=40, ncol = 4)
colnames(new_mat)<-c("Zones", "ssoilcmb", "Erosion_t", "area..sq.m.")


for ( i in 1:nrow(new_mat)){ 
  new_mat[i,4]<-as.numeric(sample(0:20, 1))
  new_mat[i,3]<-as.numeric(sample(0:20, 1))
  a<-sample(c("S2","S3","S4","S5","S1"),1)
  b<-sample(c("Deep","Moderate","Shallow"),1)
  new_mat[i,1]<-sample(c("High Precip","Moderate Precip","Low Precip"),1)
  
  new_mat[i,2]<-paste0(a,"_",b)
}

m_dt<-as.data.frame(new_mat)
m_dt$Erosion_t<-as.numeric(m_dt$Erosion_t)
m_dt$area..sq.m.<-as.numeric(m_dt$area..sq.m.)

#### calculate parea
m_dt<- m_dt %>%
  group_by(Zones)%>%
  mutate(per_er=signif((`Erosion_t`/sum(`Erosion_t`))*100,3), per_area=signif((`area..sq.m.`/sum(`area..sq.m.`))*100,3))

## Rearranging data:

a<-data.frame(m_dt$Zones,m_dt$ssoilcmb, m_dt$per_er)
b<-data.frame(m_dt$Zones,m_dt$ssoilcmb, m_dt$per_area)
c<-data.frame(Zones=m_dt$Zones,ssoilcmb=m_dt$ssoilcmb,
              Parameter=c(rep("Erosion",40),rep("Area",40)),
              Values=c(m_dt$per_er,m_dt$per_area))

### New Plot ###

ggplot(c, aes(x="", y=Values, fill=ssoilcmb)) + 
  geom_bar(stat="identity", width=1, position = position_fill())+
  coord_polar("y", start=0) + 
  facet_wrap(Zones~Parameter, nrow = 3) +
  geom_text_repel(aes(label = paste0(Values, "%")), position = position_fill(vjust = 0.5))+
  scale_fill_manual(values=my_pal(15)) +
  labs(x = NULL, y = NULL, fill = NULL, title = "Erosions")+
  theme_classic() + theme(axis.line = element_blank(),
                          axis.text = element_blank(),
                          axis.ticks = element_blank(),
                          plot.title = element_text(hjust = 0.5, color = "#666666"))
1
Your example did not work for me when I tried to run it. Regardless, if you're open to alternatives: varianceexplained.org/r/improving-pie-chartjared_mamrot
@jared_mamrot I forgot to include two libraries into the code. I tried to run it in different computer after including the library and it worked fine for me? I hope you have the Rcolorbrewer library.Samrat
All good. Thanks for fixing the example - it definitely helps your chances of getting a solution to your problem when you make it easy for people to help you.jared_mamrot

1 Answers

0
votes

If you're open to alternatives, maybe a facet_wrapped barplot will suit your needs, e.g.

library(RColorBrewer)
library(ggrepel)
library(tidyverse)

my_pal <- colorRampPalette(brewer.pal(9, "Set1"))

#### create new matrix ############
new_mat<-matrix(nrow=40, ncol = 4)
colnames(new_mat)<-c("Zones", "ssoilcmb", "Erosion_t", "area..sq.m.")


for ( i in 1:nrow(new_mat)){ 
  new_mat[i,4]<-as.numeric(sample(0:20, 1))
  new_mat[i,3]<-as.numeric(sample(0:20, 1))
  a<-sample(c("S2","S3","S4","S5","S1"),1)
  b<-sample(c("Deep","Moderate","Shallow"),1)
  new_mat[i,1]<-sample(c("High Precip","Moderate Precip","Low Precip"),1)
  
  new_mat[i,2]<-paste0(a,"_",b)
}

m_dt<-as.data.frame(new_mat)
m_dt$Erosion_t<-as.numeric(m_dt$Erosion_t)
m_dt$area..sq.m.<-as.numeric(m_dt$area..sq.m.)

#### calculate parea
m_dt<- m_dt %>%
  group_by(Zones)%>%
  mutate(per_er=signif((`Erosion_t`/sum(`Erosion_t`))*100,3),
         per_area=signif((`area..sq.m.`/sum(`area..sq.m.`))*100,3))

## Rearranging data:

a<-data.frame(m_dt$Zones,m_dt$ssoilcmb, m_dt$per_er)
b<-data.frame(m_dt$Zones,m_dt$ssoilcmb, m_dt$per_area)
c<-data.frame(Zones=m_dt$Zones,ssoilcmb=m_dt$ssoilcmb,
              Parameter=c(rep("Erosion",40),rep("Area",40)),
              Values=c(m_dt$per_er,m_dt$per_area))

### New Plot ###
c$Zones <- factor(c$Zones,levels(c$Zones)[c(2,3,1)])

ggplot(c, aes(x=ssoilcmb, y=Values, fill=ssoilcmb)) + 
  geom_col()+
  facet_wrap(Zones~Parameter, nrow = 3) +
  scale_fill_manual(values=my_pal(15)) +
  labs(x = NULL, fill = NULL, title = "Erosions")+
  theme_minimal() + theme(axis.line = element_blank(),
                          axis.ticks = element_blank(),
                          axis.text.x = element_text(angle = 90,
                                                     hjust = 1,
                                                     vjust = 0.5),
                          plot.title = element_text(hjust = 0.5,
                                                    color = "#666666"))