Personal code snippets of @tmasjc

Site powered by Hugo + Blogdown

Image by Mads Schmidt Rasmussen from unsplash.com

Minimal Bootstrap Theme by Zachary Betz

Funnel Visualization w/ Waffle Chart

Jun 14, 2020 #ggplot2 #datavis

First lets make some dummy data. Imagine we are running a campaign that gives away coupons to newly registered customers.

library(tidyverse)
old <- theme_set(theme_minimal(base_family = "Menlo") + 
                     theme(legend.position = "top", 
                           legend.spacing  = unit(10, "mm")))
pal <- c("Female" = "#fb4675", 
         "Male"   = "#51c5e5")
set.seed(1212)

prop_of_x <- function(x) {
    round(x * rnorm(1, mean = 0.5, sd = 0.05))
}

make_data_frame <- function(n) {
    N = n
    A = prop_of_x(N)
    B = prop_of_x(A)
    C = prop_of_x(B)
    D = prop_of_x(C)
    
    map(.x = c(A, B, C, D),
        .f = ~ c(rep(1, times = .x), rep(0, times = N - .x))) %>%
        set_names(c("clicks", "subscribes", "confirms", "redeems")) %>%
        as_tibble()
}

df <- bind_rows(Male   = make_data_frame(100), 
                Female = make_data_frame(100), 
                .id    = "gender")

Bar Chart

The simplest and perhaps the most effective.

df %>% 
    group_by(gender) %>% 
    summarise(across(everything(), list(sum = sum)), n = n()) %>% 
    pivot_longer(-gender, names_to = "funnel", values_to = "val") %>% 
    ggplot(aes(reorder(funnel, val), val, fill = gender)) + 
    geom_col(position = "dodge", width = 0.3) +
    scale_x_discrete(labels = function(x) str_to_title(str_remove(x, "_sum$"))) +
    scale_fill_manual(values = pal) +
    guides(fill = guide_legend(reverse = TRUE)) +
    coord_flip() +
    labs(x = "", y = "", fill = "",
         title = "The Easiest Way - Bar Chart")

Waffle Chart

An experiment…

library(waffle)

df %>% 
    group_by(gender) %>% 
    summarise(across(everything(), list(sum = sum), .names = "{col}"), 
              N = n(), 
              .groups = "keep") %>% 
    pivot_longer(
        -gender,
        names_to     = "funnel",
        values_to    = "val",
        names_ptypes = list(funnel = factor(
            levels   = c("N", "clicks", "subscribes", "confirms", "redeems"),
            ordered  = TRUE
        ))
    ) %>% 
    arrange(gender, -val) %>% 
    mutate(waffle_sq = val - lead(val), 
           waffle_sq = if_else(is.na(waffle_sq), val, waffle_sq)) %>% 
    ggplot(aes(fill = funnel, values = waffle_sq, col = gender)) +
    geom_waffle(n_rows = 10, flip = TRUE) +
    scale_color_discrete(guide = "none") +
    scale_fill_brewer(palette = "Oranges", 
                      labels = function(x) str_to_title(x)) +
    coord_equal() +
    facet_wrap(~ gender) +
    theme(panel.grid = element_blank(), 
          axis.ticks = element_blank(),
          axis.text  = element_blank())

Once again, simplicity prevails.