Home > database >  Pie chart as scatter plot with non-numeric axis in R
Pie chart as scatter plot with non-numeric axis in R

Time:09-22

I want to plot weighted pie-charts, with a non-numeric axis per Season. Every basket is a pie-chart, weighted by Frequency and showing the distribution of fruit in each basket, in order of Rank (y axis). Example of what I want the plot to look like is here, but instead of color by frequency, to have the pie-charts instead.

scatterpie did not work as my x axis is non-numeric.

I have the dataframe below:

fruit <- data.frame(
  Basket = c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O"),
  Apples = c(50, 30, 10, 5, 5, 10, 10, 5, 15, 40, 220, 150, 0, 0, 0),
  Oranges = c(1, 10, 25, 20, 15, 15, 10, 10, 0, 0, 0, 0, 0, 0, 0),
  Plums = c(0, 9, 5, 5, 5, 10, 5, 5, 10, 0, 0, 0, 0, 0, 0),
  Grapes = c(0, 0, 0, 0, 0, 60, 50, 30, 20, 4, 5, 10, 25, 5, 4),
  Frequency = c(51, 49, 40, 39, 25, 95, 75, 50, 45, 44, 225, 160, 25, 5, 4),
  Rank = c(1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5),
  Season = c("Summer", "Summer", "Summer", "Summer", "Summer", "Autumn", "Autumn", "Autumn", "Autumn", "Autumn", "Winter", "Winter", "Winter", "Winter", "Winter")
)

which looks like:

> fruit
   Basket Apples Oranges Plums Grapes Frequency Rank Season
1       A     50       1     0      0        51    1 Summer
2       B     30      10     9      0        49    2 Summer
3       C     10      25     5      0        40    3 Summer
4       D      5      20     5      0        39    4 Summer
5       E      5      15     5      0        25    5 Summer
6       F     10      15    10     60        95    1 Autumn
7       G     10      10     5     50        75    2 Autumn
8       H      5      10     5     30        50    3 Autumn
9       I     15       0    10     20        45    4 Autumn
10      J     40       0     0      4        44    5 Autumn
11      K    220       0     0      5       225    1 Winter
12      L    150       0     0     10       160    2 Winter
13      M      0       0     0     25        25    3 Winter
14      N      0       0     0      5         5    4 Winter
15      O      0       0     0      4         4    5 Winter

What I did so far is this:

fruit_melt<-melt(fruit, id.vars=c("Basket","Frequency","Rank","Season"), 
                 measure.vars=colnames(fruit)[!names(fruit) %in% c("Basket","Frequency","Rank","Season")])

ggplot(fruit_melt, aes(x=Frequency/2, y=value, colour=variable, fill=variable, width=Frequency))  
  geom_bar(width = 1, position="fill", stat = "identity")  
  coord_polar("y", start=0)   
  facet_wrap(~ Season Rank (-Frequency), ncol= 5)  theme_void() 
  theme(plot.title = element_text(hjust = 0.5, margin=margin(b=20, unit="pt"), face="bold")) 
  scale_fill_carto_d(direction = -1)  
  scale_color_carto_d(direction = -1)

Picture with current pie chart look

But I would really like to have instead:

  1. an x axis displaying the rank (top to bottom)
  2. a y axis displaying the seasons, and the basket pie charts stacked in order of rank
  3. the min size of a pie chart to be bigger. I cannot see the smallest ones

CodePudding user response:

Actually you could achieve your desired result via scatterpie. But it requires some data warngling steps. Adapting my answer on this post to your case you could convert your Season variable to a numeric. Additionally, you have to rescale the result to the range of the Rank variable as we have to use coord_fixed for scatterpie. Also we have to compute the radius manually. Note, for a nice look you have to scale the radius which reuqires sime fiddling, e.g. I used a scaling factor of .025.

library(dplyr)
library(tidyr)
library(scatterpie)
library(ggplot2)

fruit_long <- fruit |>
  pivot_longer(-c(Rank, Season, Basket, Frequency), names_to = "fruit") |>
  mutate(y = as.numeric(factor(Season, levels = c("Summer", "Autumn", "Winter"))), 
         y = scales::rescale(y, to = range(Rank)), value = value) |>
  group_by(Basket) |>
  mutate(r = 2 * sqrt(sum(value) / 2 / pi)) |> 
  ungroup()

ggplot()  
  geom_scatterpie(aes(x = Rank, y = y, fill = fruit, r = .025 * r), 
                  data = fruit_long, cols = "fruit", long_format = TRUE)  
  scale_y_continuous(
    breaks = unique(fruit_long$y), 
    labels = unique(fruit_long$Season))  
  coord_fixed()

DATA

fruit <- data.frame(
  Basket = c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O"),
  Apples = c(50, 30, 10, 5, 5, 10, 10, 5, 15, 40, 220, 150, 0, 0, 0),
  Oranges = c(1, 10, 25, 20, 15, 15, 10, 10, 0, 0, 0, 0, 0, 0, 0),
  Plums = c(0, 9, 5, 5, 5, 10, 5, 5, 10, 0, 0, 0, 0, 0, 0),
  Grapes = c(0, 0, 0, 0, 0, 60, 50, 30, 20, 4, 5, 10, 25, 5, 4),
  Frequency = c(51, 49, 40, 39, 25, 95, 75, 50, 45, 44, 225, 160, 25, 5, 4),
  Rank = c(1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5),
  Season = c("Summer", "Summer", "Summer", "Summer", "Summer", "Autumn", "Autumn", "Autumn", "Autumn", "Autumn", "Winter", "Winter", "Winter", "Winter", "Winter")
)
  • Related