1

Some data:

sub_funnel_data <- structure(list(funnelstep = structure(1:5, .Label = c("Sessions", 
"Engaged Sessions", "Subscription Funnel - Arrives on Enter Email", 
"Subscription Funnel - Arrives on Payment Details", "Direct to Paid"
), class = "factor"), N = c(92853L, 33107L, 3469L, 3149L, 113L
), Drop = c(NA, 0.356552830818606, 0.104781466155194, 0.907754396079562, 
0.0358844077484916), Rate = c(1, 0.356552830818606, 0.0373601283749583, 
0.0339138207704651, 0.00121697737283663)), row.names = c(NA, 
5L), class = c("tbl_df", "tbl", "data.frame"))

Looks like:

sub_funnel_data
# A tibble: 5 x 4
  funnelstep                                           N    Drop    Rate
* <fct>                                            <int>   <dbl>   <dbl>
1 Sessions                                         92853 NA      1      
2 Engaged Sessions                                 33107  0.357  0.357  
3 Subscription Funnel - Arrives on Enter Email      3469  0.105  0.0374 
4 Subscription Funnel - Arrives on Payment Details  3149  0.908  0.0339 
5 Direct to Paid                                     113  0.0359 0.00122

I can create a plot:

sub_funnel_data %>% 
  ggplot(aes(reorder(funnelstep, desc(funnelstep)), N)) +
  geom_bar(stat = 'identity', fill = '#39cccc') +
  coord_flip()

Looks like: enter image description here

I would like to add the drop in percentage on each step to this chart. Similar to a question I posted a few years back.

I tried to modify the solution there to my needs but failed. I like the outcome of that solution, the only real difference is that now my plot is flipped.

Here's what I tried:

sub_funnel_data <- sub_funnel_data %>% mutate(End = lag(N),
                                               xpos = 1:n() - 0.5,
                                               Diff = End - N,
                                               Percent=paste(round(Diff / End * 100, 1), "%"))

Then my attempted plot: Before coord_flip():

sub_funnel_data %>% 
  ggplot(aes(reorder(funnelstep, desc(funnelstep)), N)) +
  geom_bar(stat = 'identity', fill = '#39cccc') +
  stat_summary(aes(label = scales::comma(..y..)), fun = 'sum', 
               geom = 'text', col = 'white', vjust = 1.5) +
  geom_segment(aes(x=xpos, y = End, xend = xpos, yend = N)) +
  geom_text(aes(x = xpos, y = End - Diff / 2, label = Percent), hjust = -0.2)

enter image description here

I can already see this is flawed. But I want to use it with coord_flip() anyway:

sub_funnel_data %>% 
  ggplot(aes(reorder(funnelstep, desc(funnelstep)), N)) +
  geom_bar(stat = 'identity', fill = '#39cccc') +
  stat_summary(aes(label = scales::comma(..y..)), fun = 'sum', 
               geom = 'text', col = 'white', vjust = 1.5) +
  geom_segment(aes(x=xpos, y = End, xend = xpos, yend = N)) +
  geom_text(aes(x = xpos, y = End - Diff / 2, label = Percent), hjust = -0.2) +
  coord_flip()

Looks like: enter image description here

How can I add percentage drop off on each step to my chart? Ideally I'd like to use the Rate field in sub_funnel_data to display the corresponding percentage drop between each step. I like the lines and %ages shown at the midpoint on each chart in the linked post, I just cannot replicate it to my current use case.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
Doug Fir
  • 19,971
  • 47
  • 169
  • 299
  • Does [this](https://stackoverflow.com/questions/6017460/position-geom-text-on-dodged-barplot) help – akrun Jul 14 '21 at 22:14
  • 1
    I tried adding `position = position_dodge(width = 1)` within geom_text per that solution but the plot looks a mess. I wonder if it's because I have a factor variable, funnel step. I tried changing `geom_text(aes(x = xpos, ...` to `geom_text(aes(x = reorder(xpos, desc(funnelstep)),` but similar messy result :/ – Doug Fir Jul 14 '21 at 22:20
  • is this because of your labels. Can you try to wrap those labels with `str_wrap` – akrun Jul 14 '21 at 22:22
  • i.e. `sub_funnel_data %>% mutate(funnelstep = str_wrap(funnelstep, width = 10)) %>%ggplot` – akrun Jul 14 '21 at 22:23
  • I see a `NA %` in the Percent column – akrun Jul 14 '21 at 22:24
  • str_wrap did make the plot look slightly better before coord_flip(). BUt the plots still fundamentally off. Yes, the first item in Rate will be NA since it divides each row based on the lag of numeric column N. I.e. it's supposed to show the % that move from ecah step starting from Sessions, through Engaged Sessions... all the way to the end point Direct to Paid – Doug Fir Jul 14 '21 at 22:26

1 Answers1

2

If you reorder your aes() variables (in this case using rev()) and make some tweaks it looks ok, e.g.

library(tidyverse)

sub_funnel_data <- structure(list(funnelstep = structure(1:5, .Label = c("Sessions", 
                                                                         "Engaged Sessions", "Subscription Funnel - Arrives on Enter Email", 
                                                                         "Subscription Funnel - Arrives on Payment Details", "Direct to Paid"), 
                                                         class = "factor"), N = c(92853L, 33107L, 3469L, 3149L, 113L),
                                  Drop = c(NA, 0.356552830818606, 0.104781466155194, 0.907754396079562, 
                                           0.0358844077484916), Rate = c(1, 0.356552830818606, 0.0373601283749583, 
                                                                         0.0339138207704651, 0.00121697737283663)),
                             row.names = c(NA, 5L), class = c("tbl_df", "tbl", "data.frame"))

sub_funnel_data %>% mutate(End = lag(N),
                           xpos = 1:n() + 0.5,
                           Diff = End - N,
                           Percent=paste(round(Diff / End * 100, 1), "%")) %>% 
  ggplot(aes(x = reorder(funnelstep, desc(funnelstep)), y = N)) +
  geom_bar(stat = 'identity', fill = '#39cccc') +
  stat_summary(aes(label = scales::comma(..y..)),
               fun = "sum", geom = "text",
               col = "grey25", vjust = 0.5, hjust = 1) +
  geom_segment(aes(x = rev(xpos), y = End, xend = rev(xpos), yend = N)) +
  geom_text(aes(x = rev(xpos - 0.1), y = End - Diff / 1.5, label = Percent), hjust = -0.2) +
  coord_flip()

example_1.png

This is an alternative including the 'Rate' variable:

sub_funnel_data %>% mutate(End = lag(N),
                           xpos = 1:n() + 0.5,
                           Diff = End - N,
                           Percent = paste("\u2190 ", round(Diff / End * 100, 1), "% drop", sep = ""),
                           Rate = paste("(", round(Rate * 100, 1), "%", " of total Sessions)", sep = "")) %>% 
  ggplot(aes(x = reorder(funnelstep, desc(funnelstep)), y = N)) +
  geom_bar(stat = 'identity', fill = '#39cccc') +
  stat_summary(aes(label = paste("n = ", scales::comma(..y..), sep = "")),
               fun = "sum", geom = "text",
               col = "black", vjust = 0,
               hjust = -0.05, size = 4) +
  geom_segment(aes(x = rev(xpos), y = End, xend = rev(xpos), yend = N * 1.1)) +
  geom_text(aes(x = rev(xpos - 0.1), y = End - Diff / 1, label = Percent), hjust = -0.2) +
  geom_text(aes(x = rev(xpos - 0.7), y = End - Diff, label = Rate), color = "black", hjust = 0) +
  coord_flip()

example_2.png

Do either of these solve your problem?

jared_mamrot
  • 22,354
  • 4
  • 21
  • 46