rggplot2pie-chartggforcescatterpie

Making a scatter plot of multiple pie charts of differing sizes, using ggplot2 in R


I have a data frame containing the following data:

> data_graph
# A tibble: 12 x 4
# Groups:   ATTPRO, ATTMAR [?]
       x     y group    nb
   <dbl> <dbl> <chr> <int>
 1     0     0     1  1060
 2     0     0     2   361
 3     0     0     3   267
 4     0     1     1   788
 5     0     1     2   215
 6     0     1     3    80
 7     1     0     1   485
 8     1     0     2   168
 9     1     0     3   101
10     1     1     1  6306
11     1     1     2  1501
12     1     1     3   379

My objective is to have the following chart:

The best result approching this using ggplot2 package is only giving me bubbles, with this code. I can't find a solution to put pies within it:

library(ggplot2)
  ggplot(data_graph, aes(y = factor(y),x = factor(x))) +
  geom_point(aes(colour = group, size = nb)) +
  theme_bw() + 
  cale_size(range = c(1, 20)) +
  labs(x = "x", y = "y", color = "group", size = "nb")

enter image description here

Using scatterpie package did not help that much. This time pies are well drawn, but I can't find a way to use nb to define pie size. Also, x and y are treated as quantitative variables (I tried factor() without any chance) instead of qualitative ones. The result is pretty ugly, without a full legend.

> tmp
  x y    A    B   C
1 0 0 1060  361 267
2 0 1  788  215  80
3 1 0  485  168 101
4 1 1 6306 1501 379

library(scatterpie)
ggplot() +
   geom_scatterpie(aes(x = x, y = y), data = tmp, cols = c("A", "B", "C")) +
   coord_fixed()

enter image description here

How can this code be altered in order to have the 1st chart with the 2nd one's pies?


Solution

  • This seems to be a case for geom_arc_bar() from ggforce, with some dplyr magic. This treats x and y as continuous variables, but that's not a problem, you can pretend they are discrete by setting the right axis settings.

    The data:

    data_graph <- read.table(text = "x     y group    nb
    1     0     0     1  1060
    2     0     0     2   361
    3     0     0     3   267
    4     0     1     1   788
    5     0     1     2   215
    6     0     1     3    80
    7     1     0     1   485
    8     1     0     2   168
    9     1     0     3   101
    10     1     1     1  6306
    11     1     1     2  1501
    12     1     1     3   379", header = TRUE)
    

    The code:

    library(ggforce)
    library(dplyr)
    
    # make group a factor
    data_graph$group <- factor(data_graph$group)
    
    # add case variable that separates the four pies
    data_graph <- cbind(data_graph, case = rep(c("Aaaa", "Bbbb", "Cccc", "Dddd"), each = 3))
    
    # calculate the start and end angles for each pie
    data_graph <- left_join(data_graph,
      data_graph %>% 
        group_by(case) %>%
        summarize(nb_total = sum(nb))) %>%
      group_by(case) %>%
      mutate(nb_frac = 2*pi*cumsum(nb)/nb_total,
             start = lag(nb_frac, default = 0))
    
    # position of the labels
    data_labels <- data_graph %>% 
      group_by(case) %>%
      summarize(x = x[1], y = y[1], nb_total = nb_total[1])
    
    # overall scaling for pie size
    scale = .5/sqrt(max(data_graph$nb_total))
    
    # draw the pies
    ggplot(data_graph) + 
      geom_arc_bar(aes(x0 = x, y0 = y, r0 = 0, r = sqrt(nb_total)*scale,
                       start = start, end = nb_frac, fill = group)) +
      geom_text(data = data_labels,
                aes(label = case, x = x, y = y + scale*sqrt(nb_total) + .05),
                size =11/.pt, vjust = 0) +
      coord_fixed() +
      scale_x_continuous(breaks = c(0, 1), labels = c("X0", "X1"), name = "x axis") +
      scale_y_continuous(breaks = c(0, 1), labels = c("Y0", "Y1"), name = "y axis") +
      theme_minimal() +
      theme(panel.grid.minor = element_blank())
    

    enter image description here