rpie-chartradar-chart

Radar or Exploding Pie Charts in R (fmsb)


I am trying to show how world population has grown and will grow in five regions. I thought I could abuse the radarchart from the fmsb package to do this, making each region a category, and then each year would be a connected polygon of 5 points plotted on the rays. Obviously, the following attempt was a failure.

library(fmsb)

rnames <- c("rest", "africa", "china", "oecd", "seasia")
y1960 <- c( 759,  283,   660,  815,   517)
y1990 <- c(1405,  630,  1177, 1109,  1006)
y2020 <- c(2041, 1341,  1439, 1369,  1605)
y2060 <- c(2533, 2905,  1333, 1446,  1934)
y2100 <- c(2441, 4280,  1065, 1400,  1689)

pop <- data.frame( y1960, y1990, y2020, y2060, y2100 )
colnames(pop) <- rnames

areas <- c(rgb(1, 0, 0, 0.25),
           rgb(0, 1, 0, 0.25),
           rgb(0, 0, 1, 0.25),
           rgb(0, 1, 1, 0.25),
           rgb(1, 0, 1, 0.25))

radarchart(pop,
           cglty = 1,
           cglcol = "gray",
           plwd = 2,
           plty = 1,
           pfcol = areas)

really bad spider chart

not my proudest moment, of course. I don't even know how radarchart is calculating points. easy fix?


Solution

  • Looking at this with a couple of packages: ggradar and fmsb. Seems to me the final appearance is related to how the data is normalised.

    Alternative approach with ggradar

    library(dplyr)
    library(tidyr)
    library(scales)
    library(ggradar)
    
    rnames <- c("rest", "africa", "china", "oecd", "seasia")
    y1960 <- c( 759,  283,   660,  815,   517)
    y1990 <- c(1405,  630,  1177, 1109,  1006)
    y2020 <- c(2041, 1341,  1439, 1369,  1605)
    y2060 <- c(2533, 2905,  1333, 1446,  1934)
    y2100 <- c(2441, 4280,  1065, 1400,  1689)
    
    # bit of wrangling to get the data into required shape...
    pop_4gg <- 
      data.frame(rnames, y1960, y1990, y2020, y2060, y2100 ) |> 
      pivot_longer(starts_with("y"), names_to = "year", values_to = "pop") |> 
      pivot_wider(names_from = rnames, values_from = pop)|> 
      mutate(across(rest:seasia, rescale))
    
    ggradar(pop_4gg)
    

    Created on 2023-05-23 with reprex v2.0.2

    Added following OP's comment and revisiting a previous version using fmsb. Have tried two versions with differing approaches to setting maximum and minimum values.

    library(fmsb)
    
    areas <- c(rgb(1, 0, 0, 0.25),
               rgb(0, 1, 0, 0.25),
               rgb(0, 0, 1, 0.25),
               rgb(0, 1, 1, 0.25),
               rgb(1, 0, 1, 0.25))
    
    
    # relative to population for each country
    
    pop_by_country <- 
      rbind(summarise(pop, across(everything(), max)),
            summarise(pop, across(everything(), min)),
            pop)
      
    
    
    radarchart(pop_by_country,
               cglty = 1,
               cglcol = "gray",
               plwd = 2,
               plty = 1,
               pfcol = areas)
    

    
    
    # relative to max population
    pop_by_all <- 
      rbind(rep(max(pop), 5),
            rep(min(pop), 5),
            pop)
    
    radarchart(pop_by_all,
               cglty = 1,
               cglcol = "gray",
               plwd = 2,
               plty = 1,
               pfcol = areas)
    

    Created on 2023-05-24 with reprex v2.0.2