class: center, middle, inverse, title-slide .title[ # Tips for effective data visualization
💅 ] .author[ ### S. Mason Garrison ] --- layout: true <div class="my-footer"> <span> <a href="https://DataScience4Psych.github.io/DataScience4Psych/" target="_blank">Data Science for Psychologists</a> </span> </div> --- class: middle # Designing effective visualizations --- ## Keep it simple .pull-left-narrow[ <img src="img/pie-3d.jpg" width="100%" style="display: block; margin: auto;" /> ] .pull-right-wide[ <img src="d13_goodviz_files/figure-html/pie-to-bar-1.png" width="100%" style="display: block; margin: auto;" /> ] --- ## Use color to draw attention <br> .pull-left[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-2-1.png" width="100%" style="display: block; margin: auto;" /> ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-3-1.png" width="100%" style="display: block; margin: auto;" /> ] --- ## Tell a story <img src="img/time-series-story.png" width="95%" style="display: block; margin: auto;" /> .footnote[ Credit: Angela Zoss and Eric Monson, Duke DVS ] --- class: middle # Wrapping Up... --- class: middle # Principles for effective visualizations --- ## Principles for effective visualizations - Order matters - Put long categories on the y-axis - Keep scales consistent - Select meaningful colors - Use meaningful and nonredundant labels --- ## Data In September 2019, YouGov survey asked 1,639 GB adults the following question: .pull-left[ > In hindsight, do you think Britain was right/wrong to vote to leave EU? > >- Right to leave >- Wrong to leave >- Don't know ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-6-1.png" width="100%" style="display: block; margin: auto;" /> ] .footnote[ Source: [YouGov Survey Results](https://d25d2506sfb94s.cloudfront.net/cumulus_uploads/document/x0msmggx08/YouGov%20-%20Brexit%20and%202019%20election.pdf), retrieved Oct 7, 2019 ] --- class: middle # Order matters --- ## Alphabetical order is rarely ideal .medi.pull-left[ ``` r ggplot(brexit, aes(x = opinion)) + geom_bar() ``` ] .pull-right-wide[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-7-1.png" width="85%" style="display: block; margin: auto;" /> ] --- ## Order by frequency `fct_infreq`: Reorder factors' levels by frequency .midi[ ``` r ggplot(brexit, aes(x = fct_infreq(opinion))) + geom_bar() ``` <img src="d13_goodviz_files/figure-html/unnamed-chunk-8-1.png" width="60%" style="display: block; margin: auto;" /> ] --- ## Clean up labels .medi.pull-left[ ``` r ggplot(brexit, aes(x = opinion)) + geom_bar() + * labs( * x = "Opinion", * y = "Count" * ) ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-9-1.png" width="100%" style="display: block; margin: auto;" /> ] --- ## Alphabetical order is rarely ideal .midi.pull-left-narrow[ ``` r ggplot(brexit, aes(x = region)) + geom_bar() ``` ] .pull-right-wide[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-10-1.png" width="100%" style="display: block; margin: auto;" /> ] --- ## Use inherent level order `fct_relevel`: Reorder factor levels using a custom order ``` r brexit <- brexit %>% mutate( * region = fct_relevel( region, "london", "rest_of_south", "midlands_wales", "north", "scot" ) ) ``` --- .pull-left-wide[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-12-1.png" width="120%" style="display: block; margin: auto;" /> ] --- ## Clean up labels `fct_recode`: Change factor levels by hand ``` r brexit <- brexit %>% mutate( * region = fct_recode( region, London = "london", `Rest of South` = "rest_of_south", `Midlands / Wales` = "midlands_wales", North = "north", Scotland = "scot" ) ) ``` --- ## Clean! <img src="d13_goodviz_files/figure-html/unnamed-chunk-14-1.png" width="75%" style="display: block; margin: auto;" /> --- class: middle # Put long categories on the y-axis --- ## Long categories can be hard to read <img src="d13_goodviz_files/figure-html/unnamed-chunk-15-1.png" width="75%" style="display: block; margin: auto;" /> --- ## Move them to the y-axis .medi[ ``` r ggplot(brexit, aes(x = region)) + geom_bar() + * coord_flip() ``` <img src="d13_goodviz_files/figure-html/unnamed-chunk-16-1.png" width="55%" style="display: block; margin: auto;" /> ] --- ## Move them to the y-axis .medi[ ``` r *ggplot(brexit, aes(y = region)) + geom_bar() ``` <img src="d13_goodviz_files/figure-html/unnamed-chunk-17-1.png" width="55%" style="display: block; margin: auto;" /> ] --- ## And reverse the order of levels `fct_rev`: Reverse order of factor levels .medi.pull-left[ ``` r *ggplot(brexit, aes(y = fct_rev(region))) + geom_bar() ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-18-1.png" width="100%" style="display: block; margin: auto;" /> ] --- ## Clean up labels .medi.pull-left[ ``` r ggplot(brexit, aes(y = fct_rev(region))) + geom_bar() + * labs( * x = "Count", * y = "Region" * ) ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-19-1.png" width="100%" style="display: block; margin: auto;" /> ] --- class: middle # Pick a purpose --- ## Segmented bar plots can be hard to read .medi.pull-left-wide[ ``` r *ggplot(brexit, aes(y = region, fill = opinion)) + geom_bar() ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-20-1.png" width="100%" style="display: block; margin: auto;" /> ] --- <img src="d13_goodviz_files/figure-html/unnamed-chunk-21-1.png" width="80%" style="display: block; margin: auto;" /> --- ## Use facets .medi.pull-left-wide[ ``` r ggplot(brexit, aes(y = opinion, fill = region)) + geom_bar() + * facet_wrap(~region, nrow = 1) ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-22-1.png" width="100%" style="display: block; margin: auto;" /> ] --- <img src="d13_goodviz_files/figure-html/unnamed-chunk-23-1.png" width="80%" style="display: block; margin: auto;" /> --- ## Avoid redundancy? .medi.pull-left[ ``` r ggplot(brexit, aes(y = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1) ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-24-1.png" width="100%" style="display: block; margin: auto;" /> ] --- <img src="d13_goodviz_files/figure-html/unnamed-chunk-25-1.png" width="80%" style="display: block; margin: auto;" /> --- ## Redundancy can help tell a story .medi.pull-left[ ``` r ggplot(brexit, aes(y = opinion, fill = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1) ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-26-1.png" width="100%" style="display: block; margin: auto;" /> ] --- <img src="d13_goodviz_files/figure-html/unnamed-chunk-27-1.png" width="80%" style="display: block; margin: auto;" /> --- ## Be selective with redundancy .medi.pull-left[ ``` r ggplot(brexit, aes(y = opinion, fill = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1) + * guides(fill = FALSE) ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-28-1.png" width="100%" style="display: block; margin: auto;" /> ] --- <img src="d13_goodviz_files/figure-html/unnamed-chunk-29-1.png" width="80%" style="display: block; margin: auto;" /> --- ## Informative labels .medi.pull-left[ ``` r ggplot(brexit, aes(y = opinion, fill = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1) + guides(fill = FALSE) + labs( * title = "Was Britain right/wrong to vote to leave EU?", x = NULL, y = NULL ) ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-30-1.png" width="100%" style="display: block; margin: auto;" /> ] --- <img src="d13_goodviz_files/figure-html/unnamed-chunk-31-1.png" width="80%" style="display: block; margin: auto;" /> --- ## A bit more info .medi[ ``` r ggplot(brexit, aes(y = opinion, fill = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1) + guides(fill = FALSE) + labs( title = "Was Britain right/wrong to vote to leave EU?", * subtitle = "YouGov Survey Results, 2-3 September 2019", * caption = "Source: https://d25d2506sfb94s.cloudfront.net/cumulus_uploads/document/x0msmggx08/YouGov%20-%20Brexit%20and%202019%20election.pdf", x = NULL, y = NULL ) ``` ] --- <img src="d13_goodviz_files/figure-html/unnamed-chunk-32-1.png" width="80%" style="display: block; margin: auto;" /> --- ## Let's do better .medi[ ``` r ggplot(brexit, aes(y = opinion, fill = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1) + guides(fill = FALSE) + labs( title = "Was Britain right/wrong to vote to leave EU?", subtitle = "YouGov Survey Results, 2-3 September 2019", * caption = "Source: bit.ly/2lCJZVg", x = NULL, y = NULL ) ``` ] --- <img src="d13_goodviz_files/figure-html/unnamed-chunk-33-1.png" width="80%" style="display: block; margin: auto;" /> --- ## Fix up facet labels .medi[ ``` r ggplot(brexit, aes(y = opinion, fill = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1, * labeller = label_wrap_gen(width = 12) ) + guides(fill = FALSE) + labs( title = "Was Britain right/wrong to vote to leave EU?", subtitle = "YouGov Survey Results, 2-3 September 2019", caption = "Source: bit.ly/2lCJZVg", x = NULL, y = NULL ) ``` ] --- --- class: middle # Select meaningful colors --- ## Rainbow colors are not always the right choice .medi.pull-left[ ``` r ggplot(brexit, aes(y= region, fill = opinion)) + geom_bar(position = "fill") ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-35-1.png" width="100%" style="display: block; margin: auto;" /> ] --- <img src="d13_goodviz_files/figure-html/unnamed-chunk-36-1.png" width="80%" style="display: block; margin: auto;" /> --- ## Manually choose colors when needed .midi.pull-left-wide[ ``` r ggplot(brexit, aes(y = opinion, fill = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1, labeller = label_wrap_gen(width = 12)) + guides(fill = FALSE) + labs(title = "Was Britain right/wrong to vote to leave EU?", subtitle = "YouGov Survey Results, 2-3 September 2019", caption = "Source: bit.ly/2lCJZVg", x = NULL, y = NULL) + * scale_fill_manual(values = c( * "Wrong" = "red", * "Right" = "green", * "Don't know" = "gray" * )) ``` ] .pull-right-narrow[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-37-1.png" width="100%" style="display: block; margin: auto;" /> ] --- .center[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-38-1.png" width="80%" style="display: block; margin: auto;" /> ] --- ## Choosing better colors .center.large[ [colorbrewer2.org](https://colorbrewer2.org/) ] <img src="img/color-brewer.png" width="60%" style="display: block; margin: auto;" /> --- ## Use better colors .midi.pull-left-wide[ ``` r ggplot(brexit, aes(y = opinion, fill = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1, labeller = label_wrap_gen(width = 12)) + guides(fill = FALSE) + labs(title = "Was Britain right/wrong to vote to leave EU?", subtitle = "YouGov Survey Results, 2-3 September 2019", caption = "Source: bit.ly/2lCJZVg", x = NULL, y = NULL) + scale_fill_manual(values = c( * "Wrong" = "#ef8a62", * "Right" = "#67a9cf", * "Don't know" = "gray" )) ``` ] .pull-right-narrow[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-40-1.png" width="100%" style="display: block; margin: auto;" /> ] --- .center[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-41-1.png" width="80%" style="display: block; margin: auto;" /> ] --- ## Select theme ``` r ggplot(brexit, aes(y = opinion, fill = opinion)) + geom_bar() + facet_wrap(~region, nrow = 1, labeller = label_wrap_gen(width = 12)) + guides(fill = FALSE) + labs(title = "Was Britain right/wrong to vote to leave EU?", subtitle = "YouGov Survey Results, 2-3 September 2019", caption = "Source: bit.ly/2lCJZVg", x = NULL, y = NULL) + scale_fill_manual(values = c("Wrong" = "#ef8a62", "Right" = "#67a9cf", "Don't know" = "gray")) + * theme_minimal() ``` --- .center[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-42-1.png" width="80%" style="display: block; margin: auto;" /> ] --- ## Spot the Difference .pull-right-narrow[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-43-1.png" width="60%" style="display: block; margin: auto;" /> ] .pull-left-narrow[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-44-1.png" width="60%" style="display: block; margin: auto;" /> ] --- .your-turn[ ### .hand[Your turn!] .midi[ - `AE 07 - Brexit + Telling stories with dataviz` > `brexit.Rmd`. - Change the visualization in three different ways to tell slightly different stories with it each time. ] ] --- ## Viridis scale works well with ordinal data .medi.pull-left-wide[ ``` r ggplot(brexit, aes(y = region, fill = opinion)) + geom_bar(position = "fill") + scale_fill_viridis_d() ``` ] .pull-right[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-45-1.png" width="100%" style="display: block; margin: auto;" /> ] --- .center[ <img src="d13_goodviz_files/figure-html/unnamed-chunk-46-1.png" width="80%" style="display: block; margin: auto;" /> ] --- ### Clean up labels (Again) <img src="d13_goodviz_files/figure-html/unnamed-chunk-47-1.png" width="75%" style="display: block; margin: auto;" /> --- # Sources - Mine Çetinkaya-Rundel's Data Science in a Box ([link](https://datasciencebox.org/)) --- class: middle # Wrapping Up...