1

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"))
Samrat
  • 79
  • 1
  • 10
  • Your example did not work for me when I tried to run it. Regardless, if you're open to alternatives: http://varianceexplained.org/r/improving-pie-chart/ – jared_mamrot Jun 27 '20 at 00:02
  • @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 Jun 27 '20 at 00:40
  • 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 Jun 27 '20 at 00:47

1 Answers1

1

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"))
jared_mamrot
  • 22,354
  • 4
  • 21
  • 46
  • @ jared_mamrot thank you very much for your suggestion :) . I need to make a piechart in this case. But the ```theme_minimal()``` definitely helped as it got rid of unnecessary boxes. But the problem still remains, each facet has the labels while i would like to know if there is a way to control where to put the facet labels (either top or bottom) or (left or right). – Samrat Jun 27 '20 at 01:02
  • You can control the labels in facet_wrap with labeller: https://ggplot2.tidyverse.org/reference/labellers.html – jared_mamrot Jun 27 '20 at 09:38