Search code examples
rggplot2pie-chart

How can I move an arrow in a pie chart using ggplot2?


I have some data that I would like to plot into a pie chart. I am using ggplot2 and although I managed to get the plot, I am having some problems with the location of the arrows due they appear in the same direction together.

Fig1

Is there any possibility to move the arrows and avoid having them together or is it something due to the data?

Here is a reproducible example:

df_count <- structure(list(Expression = structure(1:3, levels = c("DOWN", 
                                                      "NS", "UP"), class = "factor"), NumGenes = c(425L, 55623L, 1138L
                                                      )), class = "data.frame", row.names = c(NA, -3L))
df_count_per <- structure(list(Expression = structure(3:1, levels = c("DOWN", 
                                                      "NS", "UP"), class = "factor"), NumGenes = c(1138L, 55623L, 425L
                                                      ), prop = c(1.99, 97.27, 0.74), ypos = c(0.995, 50.625, 99.63
                                                      )), class = "data.frame", row.names = c(NA, -3L))


library(ggplot2)
library(dplyr)
library(ggrepel)
library(forcats)

ggplot(df_count, aes(x="", y=NumGenes, fill = fct_inorder(Expression))) +
  geom_col(width=1.5, color="black") +
  coord_polar("y", start=0) +
  scale_fill_brewer(palette="Set2")+
  geom_label_repel(data = df_count_per,
                   aes(y = ypos, label = paste0(prop, "%")),
                   size = 4.5, nudge_x = 1, show.legend = FALSE) +
  guides(fill = guide_legend(title = "Expression"))+
  theme_void()

This is what I expect to have (or something similar):

fig2

Any help will be very appreciated.

Thanks very much in advance


Solution

  • The issue are the ypositions which are based on the proportions instead of the counts which you use for geom_col.

    library(ggplot2)
    library(dplyr, warn = FALSE)
    library(ggrepel)
    library(forcats)
    
    df_count_per <- df_count_per |>
      mutate(
        ypos = cumsum(NumGenes),
        ypos = .5 * (ypos + lag(ypos, default = 0))
      )
    
    ggplot(
      df_count,
      aes(x = "", y = NumGenes, fill = fct_inorder(Expression))
    ) +
      geom_col(width = 1.5, color = "black") +
      coord_polar("y", start = 0) +
      scale_fill_brewer(palette = "Set2") +
      geom_label_repel(
        data = df_count_per,
        aes(y = ypos, label = paste0(prop, "%")),
        size = 4.5, nudge_x = 1, show.legend = FALSE,
      ) +
      guides(fill = guide_legend(title = "Expression")) +
      theme_void()