2

This is my final dataset. I originally obtained this table by calculating the values separately and doing rbind between females (F) and males (M) from an original bigger dataset.

I am trying to make a handsome piechart, with the percentage labels outside and I've encountered ALL problems possible for which I cannot find a solution. Notice there is no value A for males in the dataframe.

Dataframe: sex ms n_ms n msPerc value 1 F A 1 91 0.01098901 1.098901 2 F B 18 91 0.19780220 19.780220 3 F C 65 91 0.71428571 71.428571 4 F D 7 91 0.07692308 7.692308 5 M B 11 108 0.10185185 10.185185 6 M C 86 108 0.79629630 79.629630 7 M D 11 108 0.10185185 10.185185

library(ggplot2)
library(ggrepel)
library(tidyverse)

n<- c(91, 91 , 91, 91, 108, 108, 108 )
n_ms<-c(1,18,65,7,11,86,11)
sex<- c("F","F","F","F", "M"," M","M")
ms<- c("A","B","C","D","B","C","D")

df <- data.frame(sex, ms, n_ms, n)
df[is.na(df)]<- 0
df$msPerc <- df$n_ms /df$n 
df$value <- 100*df$n_ms /df$n
df$n_ms<- as.integer(df$n_ms) # original big dataframe (doing for replication purposes)
df$n<- as.integer(df$n)

#creating position of labels
df2 <- df %>% 
  mutate(csum = rev(cumsum(rev(value))), 
         pos = value/2 + lead(csum, 1),
         pos = if_else(is.na(pos), value/2, pos))


ms_pie<-ggplot(df, aes(x="", y=msPerc, group=sex,  fill=ms)) +
  geom_bar(width = 1, stat = "identity") +
  coord_polar("y", start=0) + 
  facet_grid(.~ sex) +
  theme_void()+
  theme(legend.position="top",
        legend.text = element_text(size = 9),
        legend.title = element_text(size = 9,face = "bold"))+
  scale_fill_manual(values=c("#d7191c", "#fdae61", "#abd9e9","#5e3c99"),
                    name="Moulting stage",
                    labels=c("A","B","C","D"))+
#  geom_label(aes(label = percent(msPerc)),
#             position = position_stack(vjust = 0.5),
#             show.legend = FALSE)
# geom_text(aes(label = percent(msPerc)),size = 3,color = "black", 
#           position = position_stack(vjust = 0.5),
#           show.legend = FALSE)
 geom_label_repel(data = df2,
                  aes(y = pos, label = paste0(value, "%")),
                  size = 4.5, nudge_x = 1, show.legend = FALSE)

ms_pie

This is what happens...

enter image description here

What I would like is a piechart like this one from https://r-charts.com/part-whole/pie-chart-labels-outside-ggplot2/ but including facet_grid in variable "sex".

R charts example

geom_label

So far this is the closest I've got. Using geom_label, however my values overlap and I do not know how to separate them either... the joys of being a beginner in R.

I also tried the solutions provided in ggplot, facet, piechart: placing text in the middle of pie chart slices but coor_polar won't work with scales "free".

I would much appreciate the help. Kind regards.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Irene
  • 35
  • 4

1 Answers1

0

There are several problems with your code I've tried to clean (see comments preceeded by ####) - this should get you closer:

library(ggplot2)
library(ggrepel)
library(tidyverse)
library(scales)              #### using scales for number formatting

n<- c(91, 91 , 91, 91, 108, 108, 108 )
n_ms<-c(1,18,65,7,11,86,11)
sex<- c("F","F","F","F", "M","M","M") #### changed " M" to "M" at last but one element
ms<- c("A","B","C","D","B","C","D")

df <- data.frame(sex, ms, n_ms, n)
df[is.na(df)]<- 0
df$msPerc <- df$n_ms /df$n 
df$value <- 100*df$n_ms /df$n
df$n_ms<- as.integer(df$n_ms) # original big dataframe (doing for replication purposes)
df$n<- as.integer(df$n)

#creating position of labels
df2 <- df %>% group_by(sex) %>% #### you need to group your data by the facets you want to show
    mutate(csum = cumsum(msPerc), #### adjusted example code to use "msPerc"
         pos = msPerc/2 + lag(csum, 1),
         pos = if_else(is.na(pos), msPerc/2, pos))


ms_pie<-ggplot(df, aes(x="", y=msPerc, group=sex,  fill=ms)) +
  geom_col(width = 1) +
  coord_polar("y", start=0) + 
  facet_grid(~sex) +
  theme_void()+
  theme(legend.position="top",
        legend.text = element_text(size = 9),
        legend.title = element_text(size = 9,face = "bold"))+
  scale_fill_manual(values=c("#d7191c", "#fdae61", "#abd9e9","#5e3c99"),
                    name="Moulting stage",
                    labels=c("A","B","C","D"))+
 geom_label_repel(data = df2,
                  aes(y = pos, label = percent(msPerc, digits = 1)),
                  size = 4.5, nudge_x = 1, show.legend = FALSE)

ms_pie
Wolfgang Arnold
  • 1,252
  • 8
  • 17