class: center, middle, inverse, title-slide # deep dive: coordinate systems
facets + themes ### 2021-09-17 --- class: middle, inverse # Welcome --- ## Announcements - HW 1 feedback is posted - Review issue posted on your repo - Close it or if you have questions follow up on the issue and/or come to office hours - Issue must be closed by the time you submit your next HW - HW 2 is posted - Pay attention to code style - Keep your work organized - Label your chunks! - Aside: What's a chunk option? - Project proposals due today at 5pm - Guest lecture on Wednesday -- come with questions! --- ## Agenda for today - Wrap up: Quiz 2 recap - Coordinate systems - Facets - Themes --- ## Setup .midi[ ```r # load packages library(tidyverse) library(knitr) library(openintro) library(palmerpenguins) library(ggrepel) library(waffle) library(broom) # set default theme for ggplot2 ggplot2::theme_set(ggplot2::theme_minimal(base_size = 16)) # set default figure parameters for knitr knitr::opts_chunk$set( fig.width = 8, fig.asp = 0.618, fig.retina = 3, dpi = 300, out.width = "60%" ) # dplyr print min and max options(dplyr.print_max = 6, dplyr.print_min = 6) ``` ] --- ## Quiz 2 recap .panelset[ .panel[.panel-name[Plot] ```r ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g, color = species)) + geom_smooth(method = "lm", fullrange = TRUE, se = FALSE) ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-2-1.png" width="60%" /> ] .panel[.panel-name[Same slopes] ```r lm(body_mass_g ~ flipper_length_mm + species, data = penguins) %>% tidy() ``` ``` ## # A tibble: 4 × 5 ## term estimate std.error statistic p.value ## <chr> <dbl> <dbl> <dbl> <dbl> ## 1 (Intercept) -4031. 584. -6.90 2.55e-11 ## 2 flipper_length_mm 40.7 3.07 13.3 1.40e-32 ## 3 speciesChinstrap -207. 57.7 -3.58 3.98e- 4 ## 4 speciesGentoo 267. 95.3 2.80 5.39e- 3 ``` ] .panel[.panel-name[Different slopes] ```r lm(body_mass_g ~ flipper_length_mm * species, data = penguins) %>% tidy() ``` ``` ## # A tibble: 6 × 5 ## term estimate std.error statistic p.value ## <chr> <dbl> <dbl> <dbl> <dbl> ## 1 (Intercept) -2536. 879. -2.88 4.19e- 3 ## 2 flipper_length_mm 32.8 4.63 7.10 7.69e-12 ## 3 speciesChinstrap -501. 1523. -0.329 7.42e- 1 ## 4 speciesGentoo -4251. 1427. -2.98 3.11e- 3 ## 5 flipper_length_mm:speciesChinstrap 1.74 7.86 0.222 8.25e- 1 ## 6 flipper_length_mm:speciesGentoo 21.8 6.94 3.14 1.84e- 3 ``` ] ] --- class: middle, inverse # Coordinate systems --- ## Coordinate systems: purpose - Combine the two position aesthetics (`x` and `y`) to produce a 2d position on the plot: - linear coordinate system: horizontal and vertical coordinates - polar coordinate system: angle and radius - maps: latitude and longitude - Draw axes and panel backgrounds in coordination with the faceter coordinate systems --- ## Coordinate systems: types 1. **Linear coordinate systems:** preserve the shape of geoms - `coord_cartesian()`: the default Cartesian coordinate system, where the 2d position of an element is given by the combination of the x and y positions. - `coord_flip()`: Cartesian coordinate system with x and y axes flipped *(won't be using much now that geoms can take aesthetic mappings in x and y axes)* - `coord_fixed()`: Cartesian coordinate system with a fixed aspect ratio. *(useful only in limited circumstances)* -- 2. **Non-linear coordinate systems:** can change the shapes -- a straight line may no longer be straight. The closest distance between two points may no longer be a straight line. - `coord_trans()`: Apply arbitrary transformations to x and y positions, after the data has been processed by the stat - `coord_polar()`: Polar coordinates - `coord_map()` / `coord_quickmap()` / `coord_sf()`: Map projections --- ## Setting limits: what the plots say .small[ ```r ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g, color = species)) + geom_point() + geom_smooth() + labs(title = "Plot 1") ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g, color = species)) + geom_point() + geom_smooth() + * scale_x_continuous(limits = c(190, 220)) + scale_y_continuous(limits = c(4000, 5000)) + labs(title = "Plot 2") ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g, color = species)) + geom_point() + geom_smooth() + * xlim(190, 220) + ylim(4000, 5000) + labs(title = "Plot 3") ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g, color = species)) + geom_point() + geom_smooth() + * coord_cartesian(xlim = c(190,220), ylim = c(4000, 5000)) + labs(title = "Plot 4") ``` <img src="08-coordinates-facets-themes_files/figure-html/set-limits-1.png" width="25%" /><img src="08-coordinates-facets-themes_files/figure-html/set-limits-2.png" width="25%" /><img src="08-coordinates-facets-themes_files/figure-html/set-limits-3.png" width="25%" /><img src="08-coordinates-facets-themes_files/figure-html/set-limits-4.png" width="25%" /> ] --- ## Setting limits: what the warnings say .tiny[ ```r ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g, color = species)) + geom_point() + geom_smooth() + labs(title = "Plot 1") ``` ``` ## Warning: Removed 2 rows containing non-finite values (stat_smooth). ``` ``` ## Warning: Removed 2 rows containing missing values (geom_point). ``` ```r ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g, color = species)) + geom_point() + geom_smooth() + * scale_x_continuous(limits = c(190, 220)) + scale_y_continuous(limits = c(4000, 5000)) + labs(title = "Plot 2") ``` ``` ## Warning: Removed 235 rows containing non-finite values (stat_smooth). ``` ``` ## Warning: Removed 235 rows containing missing values (geom_point). ``` ```r ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g, color = species)) + geom_point() + geom_smooth() + * xlim(190, 220) + ylim(4000, 5000) + labs(title = "Plot 3") ``` ``` ## Warning: Removed 235 rows containing non-finite values (stat_smooth). ## Removed 235 rows containing missing values (geom_point). ``` ```r ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g, color = species)) + geom_point() + geom_smooth() + * coord_cartesian(xlim = c(190,220), ylim = c(4000, 5000)) + labs(title = "Plot 4") ``` ``` ## Warning: Removed 2 rows containing non-finite values (stat_smooth). ``` ``` ## Warning: Removed 2 rows containing missing values (geom_point). ``` ] --- ## Setting limits - Setting scale limits: Any data outside the limits is thrown away - `scale_*_continuous()`, `xlim` and `ylim` arguments - `xlim()` and `ylim()` - Setting coordinate system limits: Use all the data, but only display a small region of the plot (zooming in) - `coord_cartesian()`, `xlim` and `ylim` arguments --- ## Fixing aspect ratio with `coord_fixed()` Useful when having an aspect ratio of 1 makes sense, e.g. scores on two tests (reading and writing) on the same scale (0 to 100 points) .small[ ```r ggplot(hsb2, aes(x = read, y = write)) + geom_point() + geom_smooth(method = "lm") + geom_abline(intercept = 0, slope = 1, linetype = "dashed", color = "gray") + labs(title = "Not fixed") ggplot(hsb2, aes(x = read, y = write)) + geom_point() + geom_smooth(method = "lm") + geom_abline(intercept = 0, slope = 1, linetype = "dashed", color = "gray") + * coord_fixed() + labs(title = "Fixed") ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-6-1.png" width="40%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-6-2.png" width="40%" /> ] --- ## Transformations .small[ ```r ggplot(penguins, aes(x = bill_depth_mm, y = body_mass_g)) + geom_point() + geom_smooth(method = "lm") + labs(title = "Plot 1") ggplot(penguins, aes(x = bill_depth_mm, y = body_mass_g)) + geom_point() + geom_smooth(method = "lm") + * scale_x_log10() + scale_y_log10() + labs(title = "Plot 2") ggplot(penguins, aes(x = bill_depth_mm, y = body_mass_g)) + geom_point() + geom_smooth(method = "lm") + * coord_trans(x = "log10", y = "log10") + labs(title = "Plot 3") *ggplot(penguins, aes(x = log(bill_depth_mm, base = 10), y = log(body_mass_g, base = 10))) + geom_point() + geom_smooth(method = "lm") + labs(title = "Plot 4") ``` <img src="08-coordinates-facets-themes_files/figure-html/transformations-1.png" width="25%" /><img src="08-coordinates-facets-themes_files/figure-html/transformations-2.png" width="25%" /><img src="08-coordinates-facets-themes_files/figure-html/transformations-3.png" width="25%" /><img src="08-coordinates-facets-themes_files/figure-html/transformations-4.png" width="25%" /> ] --- ## Pie charts and bullseye charts with `coord_polar()` .small[ ```r ggplot(penguins, aes(x = 1, fill = species)) + geom_bar() + labs(title = "Stacked bar chart") ggplot(penguins, aes(x = 1, fill = species)) + geom_bar() + * coord_polar(theta = "y") + labs(title = "Pie chart") ggplot(penguins, aes(x = 1, fill = species)) + geom_bar() + coord_polar(theta = "x") + * labs(title = "Bullseye chart") ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-7-1.png" width="30%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-7-2.png" width="30%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-7-3.png" width="30%" /> ] --- class: middle .large[.hand[aside: about pie charts...]] --- ## Pie charts .task[ What do you know about pie charts and data visualization best practices? Love 'em or lose 'em? ] <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-8-1.png" width="45%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-8-2.png" width="45%" /> --- ## Pie charts: when to love 'em, when to lose 'em .pull-left-narrow[ ❤️ For categorical variables with few levels, bar charts can work well ] .pull-right-wide[ <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-9-1.png" width="50%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-9-2.png" width="50%" /> ] .pull-left-narrow[ 💔 For categorical variables with many levels, bar charts are difficult to read ] .pull-right-wide[ <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-10-1.png" width="50%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-10-2.png" width="50%" /> ] --- ## Waffle charts - Like with pie charts, work best when the number of levels represented is low - Unlike pie charts, easier to compare proportions that represent non-simple fractions <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-11-1.png" width="50%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-11-2.png" width="50%" /> --- ## Waffle charts: making of .panelset[ .panel[.panel-name[Code] ```r penguins %>% count(species) %>% ggplot(aes(fill = species, values = n)) + geom_waffle(colour = "white", flip = TRUE, make_proportional = TRUE) + #<< labs(fill = NULL, title = "Penguin species") ``` ] .panel[.panel-name[Plot] <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-12-1.png" width="60%" /> ] ] --- ## Waffle charts: enhanced theme .panelset[ .panel[.panel-name[Code] ```r penguins %>% count(species) %>% ggplot(aes(fill = species, values = n)) + geom_waffle(colour = "white", flip = TRUE, make_proportional = TRUE) + labs(fill = NULL, title = "Penguin species") + theme_enhance_waffle() #<< ``` ] .panel[.panel-name[Plot] <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-13-1.png" width="60%" /> ] ] --- class: middle .large[.hand[back to coordinate systems...]] --- ## `coord_quickmap()` .pull-left-narrow[ - Approximation that sets the aspect ratio to ensure that 1m of latitude and 1m of longitude are the same distance in the middle of the plot - Reasonable for smaller regions - Fast ] .pull-right-wide[ .panelset[ .panel[.panel-name[Cartesian] ```r ggplot(map_data("italy"), aes(long, lat, group = group)) + geom_polygon(fill = "white", color = "#008c45") + labs(x = NULL, y = NULL) ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-14-1.png" width="75%" /> ] .panel[.panel-name[Quickmap] ```r ggplot(map_data("italy"), aes(long, lat, group = group)) + geom_polygon(fill = "white", color = "#008c45") + labs(x = NULL, y = NULL) + coord_quickmap() ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-15-1.png" width="75%" /> ] ] ] --- ## `coord_map()` .pull-left-narrow[ - Uses the [**mapproj**](https://cran.r-project.org/package=mapproj) package - Uses [Mercator projection](https://en.wikipedia.org/wiki/Mercator_projection) by default, with many other options via `mapproj::mapproject() ` - Slower than `coord_quickmap()` ] .pull-right-wide[ .panelset[ .panel[.panel-name[Cartesian] ```r ggplot(map_data("state"), aes(long, lat, group = group)) + geom_polygon(fill = "white", color = "#3c3b6e") + labs(x = NULL, y = NULL) ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-16-1.png" width="75%" /> ] .panel[.panel-name[Mercator] ```r ggplot(map_data("state"), aes(long, lat, group = group)) + geom_polygon(fill = "white", color = "#3c3b6e") + labs(x = NULL, y = NULL) + coord_map() ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-17-1.png" width="75%" /> ] .panel[.panel-name[Stereographic] ```r ggplot(map_data("state"), aes(long, lat, group = group)) + geom_polygon(fill = "white", color = "#3c3b6e") + labs(x = NULL, y = NULL) + coord_map(projection = "stereographic") ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-18-1.png" width="75%" /> ] ] ] --- class: middle, inverse # Facets --- ## `facet_*()` .pull-left[ - `facet_wrap()` - "wraps" a 1d ribbon of panels into 2d - generally for faceting by a single variable - `facet_grid()` for faceting - produces a 2d grid of panels defined by variables which form the rows and columns - generally for faceting by two variables - `facet_null()`: a single plot, the default ] .pull-right[ <img src="images/grammar-of-graphics.png" width="60%" /> ] --- ## Free the scales! .small[ ```r p <- ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g)) + geom_point() p + facet_wrap(~species) + labs(title = "Same scales") p + facet_wrap(~species, scales = "free") + labs(title = "Free scales") ``` <img src="08-coordinates-facets-themes_files/figure-html/free-all-scales-1.png" width="50%" /><img src="08-coordinates-facets-themes_files/figure-html/free-all-scales-2.png" width="50%" /> ] --- ## Free some scales .small[ ```r p + facet_wrap(~species, scales = "free_x") + labs(title = "Free x scale") p + facet_wrap(~species, scales = "free_y") + labs(title = "Free x scale") ``` <img src="08-coordinates-facets-themes_files/figure-html/free-some-scales-1.png" width="50%" /><img src="08-coordinates-facets-themes_files/figure-html/free-some-scales-2.png" width="50%" /> ] --- .task[ Freeing the y scale improves the display, but it's still not satisfying. What's wrong with it? ] .small[ ```r ggplot(penguins, aes(y = species, x = body_mass_g, fill = species)) + geom_boxplot(show.legend = FALSE) + facet_grid(island ~ .) + labs(title = "Same scale and spacing") ggplot(penguins, aes(y = species, x = body_mass_g, fill = species)) + geom_boxplot(show.legend = FALSE) + facet_grid(island ~ ., scales = "free_y") + labs(title = "Free y scale, same spacing") ``` <img src="08-coordinates-facets-themes_files/figure-html/free-scales-not-spaces-1.png" width="50%" /><img src="08-coordinates-facets-themes_files/figure-html/free-scales-not-spaces-2.png" width="50%" /> ] --- ## Free spaces ```r ggplot(penguins, aes(y = species, x = body_mass_g, fill = species)) + geom_boxplot(show.legend = FALSE) + facet_grid(island ~ ., scales = "free_y", space = "free") + labs(title = "Free y scale and spacing") ``` <img src="08-coordinates-facets-themes_files/figure-html/free-spaces-1.png" width="60%" /> --- ## Highlighting across facets ```r penguins_sans_species <- penguins %>% select(-species) ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g)) + geom_point(data = penguins_sans_species, color = "gray") + geom_point(aes(color = species)) + facet_wrap(~species) ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-20-1.png" width="50%" /> --- class: middle, inverse # Themes --- ## Complete themes ```r p + theme_gray() + labs(title = "Gray") p + theme_void() + labs(title = "Void") p + theme_dark() + labs(title = "Dark") ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-21-1.png" width="33%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-21-2.png" width="33%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-21-3.png" width="33%" /> --- ## Themes from ggthemes ```r library(ggthemes) p + theme_fivethirtyeight() + labs(title = "FiveThirtyEight") p + theme_economist() + labs(title = "Economist") p + theme_wsj() + labs(title = "Wall Street Journal") ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-22-1.png" width="33%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-22-2.png" width="33%" /><img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-22-3.png" width="33%" /> --- ## Themes and color scales from ggthemes ```r p + aes(color = species) + scale_color_wsj() + theme_wsj() + labs(title = "Wall Street Journal") ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-23-1.png" width="60%" /> --- ## Modifying theme elements ```r p + labs(title = "Palmer penguins") + theme( plot.title = element_text(color = "red", face = "bold", family = "Comic Sans MS"), plot.background = element_rect(color = "red", fill = "mistyrose") ) ``` <img src="08-coordinates-facets-themes_files/figure-html/unnamed-chunk-24-1.png" width="60%" />