Search code examples
rggplot2plotchartswaffle-chart

How to display country flags on waffle chart symbols? (using, e.g,. `ggwaffle`)


I would like to create a waffle chart and use country flags in place of squares. Here is my current attempt using ggwaffle:

library(ggplot2)
library(emojifont)
library(ggwaffle)

iris2 <- iris
iris2$Species <- c("🇺🇸", "🇨🇦", "🇬🇧")

waffle_data <- waffle_iron(iris2, aes_d(group = Species))
waffle_data$label = fontawesome('fa-flag')

ggplot(waffle_data, aes(x, y, colour = group)) +
  geom_text(aes(label=label), family='fontawesome-webfont', size=7) +
  coord_equal() +
  scale_colour_waffle() +
  theme_waffle()

Created on 2023-06-18 with reprex v2.0.2

Is it possible at all with ggwaffle? I was also trying to play with ggflags but I don't see how to make these two compatible because ggflags replace points in a scatter plot.

I am also aware that Windows does not ship with country flag unicode emojis for political reasons, so base unicode wouldn't work (as in one of my previous attempts using the waffle package). So it would need to be a font that includes country flags or images thereof. Thanks for any help.


Solution

  • Using ggflags you could set the x and y coordinates to replicate a grid.

    library(ggflags)
    library(ggplot2)
    
    df1 <- data.frame(x=rep(1:15, each = 10),
                      y=rep(1:10, 15),
                      country = c(rep("us", 75), rep("ca", 50), rep("gb", 25)))
    
    ggplot(df1, aes(x, y, country=country)) + 
      geom_flag() +
      scale_country() +
      theme_void() +
      theme(legend.position = "bottom")
    

    Created on 2023-06-18 with reprex v2.0.2

    Here's a go at a function which can automate this, it's more than a bit hacky but may be useful as a starter...

    library(ggflags)
    library(ggplot2)
    
    
    
    ``` r
    #' @param in_map_var string Vector of elements to be mapped to flags
    #' @param len_x integer Length of x axis, number of flags on x axis
    #' @param na_flag string ID of a flag which is nominally used for filling in the empty grid spaces, This is a hack.
    
    waffle_map <- function(in_map_var, len_x = NA, na_flag = "ac"){
    
      # work out grid dimensions  
      var_count <- length(in_map_var)
      
      if(is.na(len_x)){
        x_count <- ceiling(sqrt(var_count))
      } else {
        x_count <- len_x
      }
    
      
      y_count <- ceiling(var_count / x_count)
      grid_count <- x_count * y_count
      
      df <- 
        data.frame(x = rep(1:y_count, each = x_count),
                   y = rep(1:x_count, y_count),
                   country = c(in_map_var, rep(na_flag, grid_count - var_count))
                   )
    
      country_4legend <- unique(df$country)[unique(df$country) != na_flag]
      
      
      
      p <- 
        ggplot(df, aes(x, y, country = country)) + 
        geom_flag(size = 8) +
        scale_country(breaks = country_4legend) +
        theme_void() +
        theme(legend.position = "bottom")
    
        if(grid_count > var_count){
        p <- 
          p +
          geom_point(data = df[var_count:grid_count, ], aes(x, y), colour = "white", size = 10)
      }
                     
      return(p)
      
    }
    
    var_2map <- c(rep("us", 75), rep("ca", 50), rep("gb", 25))
    
    waffle_map(var_2map, len_x = 15)
    

    
    waffle_map(var_2map)
    

    Created on 2023-06-18 with reprex v2.0.2