--- title: "Lab 9: Latest extension packages for visualization" author: "Brian Leung" date: "2/26/2021" output: xaringan::moon_reader: lib_dir: libs css: xaringan-themer.css nature: ratio: 21:9 highlightStyle: github highlightLines: true countIncrementalSlides: false --- ```{r setup, include=FALSE} knitr::opts_chunk$set(fig.width = 12, message = FALSE, warning = FALSE, comment = "", cache = F) library(flipbookr) library(xaringan) library(tidyverse) library(gghighlight) library(ggridges) library(ggforce) library(geofacet) library(ggchicklet) library(gganimate) # install also gifski and png library(rayshader) library(ggpointdensity) ## Data library(nycflights13) library(gapminder) data(debates2019) library(HistData) ## Theme library(hrbrthemes) ``` ```{r xaringan-themer, include=FALSE, warning=FALSE} # library(xaringanthemer) # style_mono_accent(base_color = "#23395b") ``` ## Introduction - Many new extension packages for visualization -- - `gghighlight`: highlighting specific lines and points while preserving main data -- - `geofacet`: arranging plots in a grid that resembles original geographical orientation -- - `ggridges`: visualizing multiple distributions over time or across groups -- - `ggforce`: annotating areas by group attributes -- - `ggchicklet`: creating rounded rectangle segmented column charts -- - `gganimate`: creating animations from ggplot2 objects -- - `rayshader`: creating 3D objects from ggplot2 objects -- - `flipbookr` + `xaringan`: making flipbook-style HTML slideshows --- class: middle, inverse, center # gghighlight Examples adopted from [Hiroaki Yutani](https://cran.r-project.org/web/packages/gghighlight/vignettes/gghighlight.html) and [Datanovia](https://www.datanovia.com/en/blog/gghighlight-easy-way-to-highlight-a-ggplot-in-r/) --- `r chunk_reveal("gghighlight", title = "### gghighlight :: highlighting specific lines and points while preserving main data")` ```{r "gghighlight", include = FALSE} ggplot(iris, aes(Sepal.Length, fill = Species)) + geom_histogram(bins = 30) + scale_fill_viridis_d() + gghighlight() + facet_wrap(~ Species) + scale_y_continuous(expand = c(0, 0)) + theme_minimal() ``` --- `r chunk_reveal("gghighlight2", omit = "#ROTATE", break_type = "auto", title = "### gghighlight :: highlighting specific lines and points while preserving main data")` --- `r chunk_reveal("gghighlight2", break_type = "rotate", title = "### gghighlight :: highlighting specific lines and points while preserving main data")` ```{r "gghighlight2", eval = F, echo = F} ## For each continent, find top 3 countries by avg GDP per cap gapminder %>% group_by(country, continent) %>% summarize(mean_gdpPercap = mean(gdpPercap)) %>% group_by(continent) %>% slice_max(mean_gdpPercap, n = 3) -> top_gdppc ggplot(gapminder, aes(x = year, y = gdpPercap/1000, color = country)) + geom_line(show.legend = FALSE) + scale_y_log10() + facet_wrap(~ continent) + gghighlight( country %in% top_gdppc$country, use_group_by = FALSE, calculate_per_facet = FALSE, #ROTATE calculate_per_facet = TRUE, #ROTATE label_params = list(nudge_y = 2, direction = "x", label.size = 0, label.padding = 0, box.padding = 0.5, arrow = arrow(length = unit(0.1, "cm"), type = "open")) ) + theme_minimal() ``` --- class: middle, inverse, center # geofacet Example adopted from [geofacet vignette](https://hafen.github.io/geofacet/) --- `r chunk_reveal("geofacet", omit = "#ROTATE", break_type = "auto", title = "### geofacet :: arranging plots in a grid that resembles original geographical orientation")` --- `r chunk_reveal("geofacet", omit = "#OMIT", break_type = "rotate", title = "### geofacet :: arranging plots in a grid that resembles original geographical orientation")` ```{r "geofacet", include = FALSE} as_tibble(state_unemp) %>% ggplot(aes(x = year, y = rate)) + facet_geo(~ state, grid = "us_state_grid1") + #OMIT facet_geo(~ state, grid = "us_state_grid1") + #ROTATE facet_geo(~ state, grid = "us_state_grid2") + #ROTATE geom_line(color = "steelblue") + scale_x_continuous( labels = function(x) paste0("'", substr(x, 3, 4)) ) + labs(y = "Unemployment Rate (%)", x = "Year") ``` --- class: middle, inverse, center # ggridges Example adopted from [Claus O. Wilke](https://cran.r-project.org/web/packages/ggridges/vignettes/gallery.html) --- `r chunk_reveal("ggridges", title = "### ggridges :: visualizing multiple distributions over time or across groups")` ```{r ggridges, include = FALSE} dark_colors <- c("#D55E00", "#0072B2") light_colors <- c("#D55E0050", "#0072B250") as_tibble(Aus_athletes) %>% ggplot(aes(x = height, y = sport, fill = sex, color = sex, point_color = sex)) + geom_density_ridges( jittered_points = TRUE, scale = 1, rel_min_height = .01, point_shape = "|", point_size = 3, size = 0.25, position = position_points_jitter(height = 0) ) + scale_y_discrete(expand = c(0, 0)) + scale_x_continuous(expand = c(0, 0), name = "height [cm]") + scale_fill_manual(values = light_colors) + scale_color_manual(values = dark_colors) + scale_discrete_manual("point_color", values = dark_colors) + guides(fill = guide_legend( override.aes = list(point_color = NA, fill = light_colors), color = "none", point_color = "none") ) + coord_cartesian(clip = "off") + ggtitle("Height in Australian athletes") + theme_ridges(center = TRUE) ``` --- class: middle, inverse, center # ggforce Example taken from [Edgar Ruiz](https://rviews.rstudio.com/2019/09/19/intro-to-ggforce/) --- `r chunk_reveal("ggforce", omit = "#ROTATE", break_type = "auto", title = "### ggforce :: annotating areas by group attributes")` --- `r chunk_reveal("ggforce", omit = "#OMIT", break_type = "rotate", title = "### ggforce :: annotating areas by group attributes")` ```{r ggforce, include = FALSE} airports %>% filter(lon < 0, tzone != "\\N") %>% ggplot(aes(x = lon, y = lat, color = tzone)) + geom_point() + geom_mark_rect() + #OMIT geom_mark_rect(aes(label = tzone)) + #ROTATE geom_mark_hull(aes(label = tzone)) + #ROTATE geom_mark_hull(aes(label = tzone, fill = tzone)) + #ROTATE guides(fill = "none", color = "none") + theme_no_axes() ``` ---- `r chunk_reveal("ggforce2", break_type = "non_seq", title = "### ggforce :: annotating areas by group attributes")` ```{r ggforce2, include = FALSE} airports %>% filter(lon < 0, tzone != "\\N") %>% ggplot(aes(x = lon, y = lat, color = tzone)) + geom_point() + geom_mark_hull( aes(label = tzone, fill = tzone), expand = unit(3, "mm") #BREAK2 ) + guides(fill = "none", color = "none") + theme_no_axes() + facet_zoom(x = tzone == "America/Los_Angeles") #BREAK3 ``` --- class: middle, inverse, center # ggchicklet Example taken from [Bob Rudis](https://cinc.rud.is/web/packages/ggchicklet/) --- `r chunk_reveal("ggchicklet1", title = "### ggchicklet :: creating rounded rectangle segmented column charts")` ```{r "ggchicklet1", include = FALSE} debates2019 %>% filter(debate_group == 1) %>% mutate( speaker = fct_reorder(speaker, elapsed, .fun = sum, .desc = FALSE), topic = fct_other(topic, keep = c("Immigration", "Economy", "Climate Change", "Gun Control", "Healthcare", "Foreign Policy")) ) -> debates2019 topic_colors <- c("Immigration" = "#ae4544", "Economy" = "#d8cb98", "Climate Change" = "#a4ad6f", "Gun Control" = "#cc7c3a", "Healthcare" = "#436f82", "Foreign Policy" = "#7c5981", "Other" = "#cccccc") ``` --- `r chunk_reveal("ggchicklet2", title = "### ggchicklet :: creating rounded rectangle segmented column charts")` ```{r "ggchicklet2", include = FALSE} ggplot(debates2019, aes(x = speaker, y = elapsed, group = timestamp, fill = topic)) + geom_chicklet(width = 0.75) + scale_y_continuous( expand = c(0, 0.0625), position = "right", breaks = seq(0, 14, 2), labels = c(0, sprintf("%d min.", seq(2, 14, 2))) ) + scale_fill_manual( name = NULL, values = topic_colors, breaks = setdiff(unique(debates2019$topic), "Other") ) + guides(fill = guide_legend(nrow = 1)) + coord_flip() + theme_ipsum_rc(grid="X") + theme(axis.text.x = element_text(color = "gray60", size = 10)) + theme(legend.position = "top") + labs( x = NULL, y = NULL, fill = NULL, title = "How Long Each Candidate Spoke", subtitle = "Nights 1 & 2 of the June 2019 Democratic Debates", caption = "Each bar segment represents the length of a candidate’s response to a question.\n\nOriginals \n\nby @nytimes Weiyi Cai, Jason Kao, Jasmine C. Lee, Alicia Parlapiano and Jugal K. Patel\n\n#rstats reproduction by @hrbrmstr" ) ``` --- class: middle, inverse, center # gganimate Examples taken from [gganimate vignette](https://gganimate.com/index.html) and [Evangeline Reynolds](https://evamaerey.github.io/little_flipbooks_library/about/what_the_flipbook) --- `r chunk_reveal("gganimate", title = "### gganimate :: creating animations from ggplot2 objects")` ```{r gganimate, include = FALSE} gapminder %>% ggplot(aes(x = gdpPercap, y = lifeExp, size = pop, colour = country)) + geom_point(alpha = 0.7, show.legend = FALSE) + facet_wrap(~ continent) + scale_x_log10() + scale_size(range = c(2, 12)) + scale_colour_manual(values = country_colors) + labs(title = 'Year: {frame_time}', x = 'GDP per capita', y = 'life expectancy') + transition_time(year) + ease_aes('linear') ``` --- `r chunk_reveal("gganimate2", title = "### gganimate :: creating animations from ggplot2 objects")` ```{r gganimate2, include = FALSE} gapminder %>% group_by(year) %>% arrange(year, desc(gdpPercap)) %>% mutate(rank = row_number()) %>% filter(rank <= 10) -> gdppc_ranked_year ``` --- `r chunk_reveal("gganimate3", title = "### gganimate :: creating animations from ggplot2 objects")` ```{r gganimate3, include = FALSE} gdppc_ranked_year %>% ggplot(aes(xmin = 0, xmax = gdpPercap / 1000, ymin = rank - 0.45, ymax = rank + 0.45, fill = continent)) + geom_rect(alpha = 0.8) + facet_wrap(~ year) + geom_text(aes(y = rank, label = country), x = -5, hjust = "right") + scale_x_continuous(limits = c(-45, 115), breaks = seq(0, 100, 25)) + scale_y_reverse() + scale_fill_brewer(palette = "Set3") + labs(y = NULL, x = "GDP per capita (thousands)") + theme(axis.line.x = element_line(), axis.line.y = element_blank(), axis.ticks.y = element_blank(), axis.text.y = element_blank(), panel.background = element_blank()) -> gdppc_plot ``` --- `r chunk_reveal("gganimate4", title = "### gganimate :: creating animations from ggplot2 objects")` ```{r gganimate4, include = FALSE} gdppc_plot + facet_null() + geom_text(aes(label = as.factor(year)), x = 90 , y = -10, size = 15, check_overlap = TRUE) + transition_time(year) -> gdppc_animate animate(gdppc_animate, fps = 20, duration = 15, end_pause = 20) ``` --- class: inverse, center, middle # rayshader Example taken from [Tyler Morgan-Wall](https://gist.github.com/tylermorganwall/2f3ca112b9cd13972e02e1062670b735) --- `r chunk_reveal("rayshader", title = "### rayshader :: translating ggplot2 objects into 3D data visualizations")` ```{r "rayshader", include = FALSE} deaths <- Snow.deaths head(deaths) streets <- Snow.streets head(streets) themeval <- theme(panel.border = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_blank(), axis.ticks = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank(), legend.key = element_blank(), plot.margin = unit(c(0.5, 0, 0, 0), "cm")) ``` --- `r chunk_reveal("rayshader2", title = "### rayshader :: translating ggplot2 objects into 3D data visualizations")` ```{r "rayshader2", include = FALSE} ggplot() + geom_path(data = streets, aes(x = x, y = y, group = street), color = "grey50") + geom_pointdensity(data = deaths, aes(x = x, y = y), size = 1, adjust = 0.1) + coord_fixed() + scale_color_viridis_c() + theme_bw() + themeval -> js ggplot() + geom_path(data = streets, aes(x = x, y = y, group = street), color = "white") + geom_pointdensity(data = deaths, aes(x = x, y = y), size = 1, adjust = 0.1) + coord_fixed() + scale_color_viridis_c() + theme_bw() + themeval -> js2 ``` --- `r chunk_reveal("rayshader3", title = "### rayshader :: translating ggplot2 objects into 3D data visualizations")` ```{r "rayshader3", include = FALSE} plot_gg( list(js,js2), multicore = TRUE, raytrace = TRUE, height_aes = "color", shadow_intensity = 0.3, width = 8, height = 7, soliddepth = -100, save_height_matrix = TRUE, background = "#f5e9dc", shadowcolor= "#4f463c", windowsize = c(1000, 1000), preview = TRUE ) -> ggheight ``` --- ### A bit more code to generate a .gif with `gifski` ```{r "rayshader4", eval = F} # ## Add label # render_label(ggheight, "Water Pump", x=1110,y=1020,z=390, textsize = 2) # # ## Generate animation # for(i in 1:360) { # render_camera(phi=20,theta=45+i,fov=70,zoom=0.25) # render_depth(focus=0.77, # title_text = "John Snow's London cholera map, # of nearest neighbors", # title_size = 35, # filename = glue::glue("snow{i}")) # } # # ## Generate gif # files <- fs::dir_ls("JohnSnow/") # num <- as.numeric(str_extract(files, "\\d+")) # frame <- tibble(files, num) %>% arrange(num) # gifski::gifski(frame$files, gif_file = "snow.gif", delay = 0.04, loop = TRUE, progress = TRUE) ``` --- ### Final animation of London cholera clusters by John Snow

animated

--- ### Lastly, how do I write these slides? - `flipbookr` package by [Evangeline Reynolds](https://github.com/EvaMaeRey/flipbookr): "side-by-side, aligned, incremental code-output evolution" -- - Together with `xaringan` package by [Yihui Xie](https://github.com/yihui/xaringan) for HTML slideshows -- - Take a look at my source `.Rmd`, or [vignettes by Reynolds](https://evamaerey.github.io/little_flipbooks_library/about/what_the_flipbook) if interested --- class: middle, inverse, center # Thank you! ```{css, eval = TRUE, echo = FALSE} .remark-code{line-height: 1.5; font-size: 90%} ```