class: inverse, left, bottom background-image: url(https://images.unsplash.com/photo-1542204165-65bf26472b9b?auto=format&fit=crop&q=80&w=1548&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D) background-size: cover # .Large[# [prop is hard to use](https://github.com/tidyverse/ggplot2/issues/5505)] ## .small[featuring [ggplot2/issues/5505]() ...] #### .tiny[Gina Reynolds | 2023-10-25 |Image credit: Denise Jans, Upsplash] ??? Title --- count: false .panel1-feature-auto[ ```r *to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} ``` ] .panel2-feature-auto[ ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} *library(tidyverse) ``` ] .panel2-feature-auto[ ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) *theme_set(theme_bw(base_size = 20)) ``` ] .panel2-feature-auto[ ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) *Titanic ``` ] .panel2-feature-auto[ ``` ## , , Age = Child, Survived = No ## ## Sex ## Class Male Female ## 1st 0 0 ## 2nd 0 0 ## 3rd 35 17 ## Crew 0 0 ## ## , , Age = Adult, Survived = No ## ## Sex ## Class Male Female ## 1st 118 4 ## 2nd 154 13 ## 3rd 387 89 ## Crew 670 3 ## ## , , Age = Child, Survived = Yes ## ## Sex ## Class Male Female ## 1st 5 1 ## 2nd 11 13 ## 3rd 13 14 ## Crew 0 0 ## ## , , Age = Adult, Survived = Yes ## ## Sex ## Class Male Female ## 1st 57 140 ## 2nd 14 80 ## 3rd 75 76 ## Crew 192 20 ``` ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% * data.frame() ``` ] .panel2-feature-auto[ ``` ## Class Sex Age Survived Freq ## 1 1st Male Child No 0 ## 2 2nd Male Child No 0 ## 3 3rd Male Child No 35 ## 4 Crew Male Child No 0 ## 5 1st Female Child No 0 ## 6 2nd Female Child No 0 ## 7 3rd Female Child No 17 ## 8 Crew Female Child No 0 ## 9 1st Male Adult No 118 ## 10 2nd Male Adult No 154 ## 11 3rd Male Adult No 387 ## 12 Crew Male Adult No 670 ## 13 1st Female Adult No 4 ## 14 2nd Female Adult No 13 ## 15 3rd Female Adult No 89 ## 16 Crew Female Adult No 3 ## 17 1st Male Child Yes 5 ## 18 2nd Male Child Yes 11 ## 19 3rd Male Child Yes 13 ## 20 Crew Male Child Yes 0 ## 21 1st Female Child Yes 1 ## 22 2nd Female Child Yes 13 ## 23 3rd Female Child Yes 14 ## 24 Crew Female Child Yes 0 ## 25 1st Male Adult Yes 57 ## 26 2nd Male Adult Yes 14 ## 27 3rd Male Adult Yes 75 ## 28 Crew Male Adult Yes 192 ## 29 1st Female Adult Yes 140 ## 30 2nd Female Adult Yes 80 ## 31 3rd Female Adult Yes 76 ## 32 Crew Female Adult Yes 20 ``` ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% * ggplot(aes(x = Sex, fill = Survived, weight = Freq)) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_06_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + * geom_bar(position = "dodge") ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_07_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group * aes(y = after_stat(prop), group = Survived) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_08_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + * aes(label = to_percent(after_stat(prop))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_09_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + * stat_count(geom = "text", size = 4, * position = * position_dodge2(width = .9, preserve = "single")) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_10_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + * scale_y_continuous(labels = scales::percent_format()) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_11_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total * aes(y = after_stat(count / sum(count))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_12_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + * aes(label = to_percent(after_stat(count / sum(count)))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_13_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + aes(label = to_percent(after_stat(count / sum(count)))) + # Proportion per x position * aes(y = after_stat(count / ave(count, x, FUN = sum))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_14_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + aes(label = to_percent(after_stat(count / sum(count)))) + # Proportion per x position aes(y = after_stat(count / ave(count, x, FUN = sum))) + * aes(label = to_percent(after_stat(count / ave(count, x, FUN = sum)))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_15_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + aes(label = to_percent(after_stat(count / sum(count)))) + # Proportion per x position aes(y = after_stat(count / ave(count, x, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, x, FUN = sum)))) + * facet_wrap(~ Class) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_16_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + aes(label = to_percent(after_stat(count / sum(count)))) + # Proportion per x position aes(y = after_stat(count / ave(count, x, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, x, FUN = sum)))) + facet_wrap(~ Class) + # Proportion per panel * aes(y = after_stat(count / ave(count, PANEL, FUN = sum))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_17_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + aes(label = to_percent(after_stat(count / sum(count)))) + # Proportion per x position aes(y = after_stat(count / ave(count, x, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, x, FUN = sum)))) + facet_wrap(~ Class) + # Proportion per panel aes(y = after_stat(count / ave(count, PANEL, FUN = sum))) + * aes(label = to_percent(after_stat(count / ave(count, PANEL, FUN = sum)))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_18_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + aes(label = to_percent(after_stat(count / sum(count)))) + # Proportion per x position aes(y = after_stat(count / ave(count, x, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, x, FUN = sum)))) + facet_wrap(~ Class) + # Proportion per panel aes(y = after_stat(count / ave(count, PANEL, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, PANEL, FUN = sum)))) + # Proportion per panel and x position * aes(y = after_stat(count / ave(count, x, PANEL, FUN = sum))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_19_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + aes(label = to_percent(after_stat(count / sum(count)))) + # Proportion per x position aes(y = after_stat(count / ave(count, x, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, x, FUN = sum)))) + facet_wrap(~ Class) + # Proportion per panel aes(y = after_stat(count / ave(count, PANEL, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, PANEL, FUN = sum)))) + # Proportion per panel and x position aes(y = after_stat(count / ave(count, x, PANEL, FUN = sum))) + * aes(label = to_percent(after_stat(count / ave(count, x, PANEL, FUN = sum)))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_20_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + aes(label = to_percent(after_stat(count / sum(count)))) + # Proportion per x position aes(y = after_stat(count / ave(count, x, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, x, FUN = sum)))) + facet_wrap(~ Class) + # Proportion per panel aes(y = after_stat(count / ave(count, PANEL, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, PANEL, FUN = sum)))) + # Proportion per panel and x position aes(y = after_stat(count / ave(count, x, PANEL, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, x, PANEL, FUN = sum)))) + # Proportion per panel and fill * aes(y = after_stat(count / ave(count, fill, PANEL, FUN = sum))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_21_output-1.png)<!-- --> ] --- count: false .panel1-feature-auto[ ```r to_percent = function(x){(100*x) %>% round(1) %>% paste("%")} library(tidyverse) theme_set(theme_bw(base_size = 20)) Titanic %>% data.frame() %>% ggplot(aes(x = Sex, fill = Survived, weight = Freq)) + geom_bar(position = "dodge") + # Proportion per group aes(y = after_stat(prop), group = Survived) + aes(label = to_percent(after_stat(prop))) + stat_count(geom = "text", size = 4, position = position_dodge2(width = .9, preserve = "single")) + scale_y_continuous(labels = scales::percent_format()) + # Proportion of total aes(y = after_stat(count / sum(count))) + aes(label = to_percent(after_stat(count / sum(count)))) + # Proportion per x position aes(y = after_stat(count / ave(count, x, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, x, FUN = sum)))) + facet_wrap(~ Class) + # Proportion per panel aes(y = after_stat(count / ave(count, PANEL, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, PANEL, FUN = sum)))) + # Proportion per panel and x position aes(y = after_stat(count / ave(count, x, PANEL, FUN = sum))) + aes(label = to_percent(after_stat(count / ave(count, x, PANEL, FUN = sum)))) + # Proportion per panel and fill aes(y = after_stat(count / ave(count, fill, PANEL, FUN = sum))) + * aes(label = to_percent(after_stat(count / ave(count, fill, PANEL, FUN = sum)))) ``` ] .panel2-feature-auto[ ![](prop-is-hard-to-use_files/figure-html/feature_auto_22_output-1.png)<!-- --> ] <style> .panel1-feature-auto { color: black; width: 49%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel2-feature-auto { color: black; width: 49%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel3-feature-auto { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 80% } </style> --- ```r layer_all_stages <- function(){ a <- ggtrace::layer_before_stat() %>% head(3) b <- ggtrace::layer_after_stat() %>% head(3) c <- ggtrace::layer_before_geom() %>% head(3) d <- ggtrace::layer_after_scale() %>% head(3) list(before_stat = a, after_stat = b, before_geom = c, after_scale = d) } layer_all_stages() ``` ``` ## $before_stat ## # A tibble: 3 × 5 ## group x fill weight PANEL ## <int> <mppd_dsc> <fct> <dbl> <fct> ## 1 1 1 No 0 1 ## 2 1 1 No 0 2 ## 3 1 1 No 35 3 ## ## $after_stat ## # A tibble: 3 × 8 ## count prop x width flipped_aes group fill PANEL ## <dbl> <dbl> <mppd_dsc> <dbl> <lgl> <int> <fct> <fct> ## 1 118 0.967 1 0.9 FALSE 1 No 1 ## 2 4 0.0328 2 0.9 FALSE 1 No 1 ## 3 62 0.305 1 0.9 FALSE 2 Yes 1 ## ## $before_geom ## # A tibble: 3 × 10 ## label y count prop x width flipped_aes group fill PANEL ## <chr> <dbl> <dbl> <dbl> <mppd_dsc> <dbl> <lgl> <int> <fct> <fct> ## 1 96.7 % 0.967 118 0.967 1 0.9 FALSE 1 No 1 ## 2 3.3 % 0.0328 4 0.0328 2 0.9 FALSE 1 No 1 ## 3 30.5 % 0.305 62 0.305 1 0.9 FALSE 2 Yes 1 ## ## $after_scale ## # A tibble: 3 × 17 ## fill label y count prop x flipped_aes group PANEL ymin ymax ## <chr> <chr> <dbl> <dbl> <dbl> <mppd> <lgl> <int> <fct> <dbl> <dbl> ## 1 #F8766D 96.7 % 0.967 118 0.967 0.775 FALSE 1 1 0 0.967 ## 2 #F8766D 3.3 % 0.0328 4 0.0328 1.775 FALSE 1 1 0 0.0328 ## 3 #00BFC4 30.5 % 0.305 62 0.305 1.225 FALSE 2 1 0 0.305 ## # ℹ 6 more variables: xmin <mppd_dsc>, xmax <mppd_dsc>, colour <lgl>, ## # linewidth <dbl>, linetype <dbl>, alpha <lgl> ``` --- ```r prop_by <- function(...) { count <- evalq(count, parent.frame()) if (length(list(...)) == 0) { count / sum(count) } else { count / ave(count, ..., FUN = function(x) sum(abs(x))) } } ggplot(diamonds, aes(cut, fill = color)) + geom_bar(position = "dodge") + aes(y = after_stat(prop_by())) ``` ![](prop-is-hard-to-use_files/figure-html/unnamed-chunk-2-1.png)<!-- --> --- ### Contribute - https://github.com/EvaMaeRey/ggcirclepack --- ### Check out {packcircles} which does the computation in ggcirclepack - https://github.com/mbedward/packcircles --- ### Check out flipbookr, used to build this featurette - https://github.com/EvaMaeRey/flipbookr - discussion: https://github.com/EvaMaeRey/flipbookr/blob/master/docs/draft_jasa_submission.pdf --- ### Check out more featurettes - https://EvaMaeRey.github.io/featurette <style type="text/css"> .remark-code{line-height: 1.5; font-size: 85%} @media print { .has-continuation { display: block; } } </style>