class: center, middle, inverse, title-slide # Obraz jest wart tysiąca słów ## pasywne i interaktywne wizualizacje w R ### Julia Romanowska ### BIOS, UiB ### 25.11.2020 --- class: middle, center ## Julia Romanowska ### biostatystyka, wizualizacje, data scientist ### współzałożycielka R-Ladies Bergen **Uniwersytet w Bergen, Norwegia** https://jrom.bitbucket.io/homepage/ ??? Witam, kilka słów o mnie - jestem bioinformatykiem na Uniwersytecie w Bergen w Norwegii, ale moją pasją są wizualizacje. W dzisiejszym świecie, gdzie jest tyle danych, tyle informacji, że nikt nie jest w stanie tego przetrawić, coraz ważniejsza jest dobra wizualizacja tych danych, żeby przekonać siebie lub innych o tym jaką wiadomość przekazują te dane. --- ## INFO - [github repozytorium](https://github.com/jromanowska/Wizualizacje_R) z kodem i tą prezentacją - [slajdy online](https://jromanowska.github.io/Wizualizacje_R/) - prezentacja zrobiona w Rmarkdown, z użyciem: - `xaringan`, - `xaringanthemer` - `xaringanextra` - `flipbookr` - kod na slajdach można skopiować (*"Copy code"* w górnym prawym rogu) - jeśli chcesz zobaczyć notatki, kliknij *"p"* ??? Zanim zaczniemy, kilka informacji - repozytorium zawiera kod i prezentację. --- class: left, inverse, bottom # PLAN ## Wstęp - jak projektować grafikę? ## Krótko o ggplot2 ## Interaktywne grafy ### na szybko ### i trochę wolniej ??? Oto plan na następne 28 minut - najpierw dam kilka wskazówek co do tego jak zaplanować naszą wizualizację, potem, pokażę krótko ciekawe rzeczy w ggplot2 i na końcu pokażę jak w R można robić interaktywne wizualizacje - prosto i trochę bardziej zaawansowanie. --- *For a graph to be effective, it must be easy for its audience to decode and interpret.* [Duke, S. P. et al. Stat.Med. 34 (2015)](https://doi.org/10.1002/sim.6549) <br> ![](INFO_Napoleon.jpg) <p style="font-size: small; font-style: italic;">[src: Charles Joseph Minard, Napoleon’s March InfoGraphic]</p> ??? Ten rysunek pewnie widzieliście nie raz. Wyprawa Napoleona na Moskwę podsumowana w pięknym grafie francuskiego statystyka Minard'a. Przypatrzmy się trochę. Na tym rysunku jest tak naprawdę 5 różnych typów danych: - przede wszystkim, dane geograficzne - grubość linii pokazuje jak wielu żołnierzy miał Napoleon na kolejnych odcinkach - kolor linii mówi nam czy to był marsz na Moskwę czy odwrót - na dole mamy czas w trakcie odwrotu - oraz temperaturę, bo to nie tylko rosyjskie wojska, ale też zima wykończyła Napoleona OK, ale jak zaprojektować taką piękną wizualizację? Czy jest jakiś łatwy przepis? --- ## Wstęp - jak projektować grafikę? - eksploruj dane - wypróbuj różne typy grafów **na kartce!** - wybierz kolorystykę - jaką wiadomość przekazuje grafika? ??? _Łatwego_ przepisu nie ma, ale są wskazówki. Przede wszystkim, trzeba poznać dane - więc sprawdzić jakiego są typu, czy są braki danych, czy niektóre elementy są zależne od siebie, itp. Potem, można zacząć myśleć o tym jaki typ grafu wybrać, ale *uwaga* - najlepiej szkicować ołówkiem na kartce! Jeśli już uznamy, że znaleźliśmy ten najlepszy typ, to można wybrać kolory i sprawdzić jak będzie to wyglądało np. w ggplot - czy rzeczywiście przedstawia ten graf to co chcieliśmy? -- - dobre książki: - ["Info We Trust", RJ Andrews](https://www.amazon.com/Info-We-Trust-Inspire-World/dp/1119483891) - ["Storytelling with Data"](https://www.amazon.com/Storytelling-Data-Visualization-Business-Professionals/dp/1119002257) and ["Storytelling with Data / Let's practice!"](https://www.amazon.com/Storytelling-Data-Cole-Nussbaumer-Knaflic/dp/1119621496), Cole Nussbaumer Knaflic ??? Nie mam tu czasu, żeby pokryć całą tematykę wyboru typu grafu czy kolorystyki. Jest o tym mnóstwo książek - ja polecam te trzy, które czyta się bardzo łatwo, gdyż nie skupiają się na technicznych detaljach, a raczej na ogólnych zasadach. --- class: inverse, left, middle ## ggplot2 i rozszerzenia ??? OK - teraz czas na akcję - ggplot2. Zakładam, że umiecie trochę rysować w R, jeśli nie, to jest mnóstwo wspaniałych tutoriali online. --- <div style="float: right; position: fixed; right: 10px; top: 10px;"> <img style="float: right; position: relative; width: 120px" src="palmer_penguins_logo.png" alt="ggiraph"/><br> </div> [palmerpenguins](https://allisonhorst.github.io/palmerpenguins/) <br><br><br> ```r penguins ``` ``` ## # A tibble: 344 x 8 ## species island bill_length_mm bill_depth_mm flipper_length_… body_mass_g ## <fct> <fct> <dbl> <dbl> <int> <int> ## 1 Adelie Torge… 39.1 18.7 181 3750 ## 2 Adelie Torge… 39.5 17.4 186 3800 ## 3 Adelie Torge… 40.3 18 195 3250 ## 4 Adelie Torge… NA NA NA NA ## 5 Adelie Torge… 36.7 19.3 193 3450 ## 6 Adelie Torge… 39.3 20.6 190 3650 ## 7 Adelie Torge… 38.9 17.8 181 3625 ## 8 Adelie Torge… 39.2 19.6 195 4675 ## 9 Adelie Torge… 34.1 18.1 193 3475 ## 10 Adelie Torge… 42 20.2 190 4250 ## # … with 334 more rows, and 2 more variables: sex <fct>, year <int> ``` ??? Będę używać takiego zestawu danych, który jest dostępny w pakiecie "palmerpenguins" i który zawiera informacje o morfologii pingwinów z pewnych wysp. --- count: false .panel1-penguins_species-auto[ ```r *ggplot(data = penguins) ``` ] .panel2-penguins_species-auto[ ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species_auto_01_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species-auto[ ```r ggplot(data = penguins) + * aes(x = bill_length_mm, * y = bill_depth_mm) ``` ] .panel2-penguins_species-auto[ ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species_auto_02_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species-auto[ ```r ggplot(data = penguins) + aes(x = bill_length_mm, y = bill_depth_mm) + * geom_point( * aes(color = species, * shape = species), * size = 2) ``` ] .panel2-penguins_species-auto[ ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species_auto_03_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species-auto[ ```r ggplot(data = penguins) + aes(x = bill_length_mm, y = bill_depth_mm) + geom_point( aes(color = species, shape = species), size = 2) + * geom_smooth(method = "lm", * se = FALSE, * aes(color = species)) ``` ] .panel2-penguins_species-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species_auto_04_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species-auto[ ```r ggplot(data = penguins) + aes(x = bill_length_mm, y = bill_depth_mm) + geom_point( aes(color = species, shape = species), size = 2) + geom_smooth(method = "lm", se = FALSE, aes(color = species)) *penguins_default <- last_plot() ``` ] .panel2-penguins_species-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species_auto_05_output-1.png)<!-- --> ] <style> .panel1-penguins_species-auto { color: black; width: 38.6060606060606%; hight: 32%; float: left; padding-left: 1%; font-size: 50% } .panel2-penguins_species-auto { color: black; width: 59.3939393939394%; hight: 32%; float: left; padding-left: 1%; font-size: 50% } .panel3-penguins_species-auto { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 50% } </style> ??? Podstawowe rysowanie w ggplot2: - 'aesthetics' + data + geom --- count: false .panel1-penguins_species2-auto[ ```r *penguins_default ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_01_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species2-auto[ ```r penguins_default + * scale_color_manual( * values = c("darkorange", * "darkorchid", * "cyan4") * ) ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_02_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species2-auto[ ```r penguins_default + scale_color_manual( values = c("darkorange", "darkorchid", "cyan4") ) + * facet_grid(rows = vars(species)) ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_03_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species2-auto[ ```r penguins_default + scale_color_manual( values = c("darkorange", "darkorchid", "cyan4") ) + facet_grid(rows = vars(species)) + * labs(title = * "Penguin species differentation") ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_04_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species2-auto[ ```r penguins_default + scale_color_manual( values = c("darkorange", "darkorchid", "cyan4") ) + facet_grid(rows = vars(species)) + labs(title = "Penguin species differentation") + * labs(subtitle = * "based on bill depth and bill length") ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_05_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species2-auto[ ```r penguins_default + scale_color_manual( values = c("darkorange", "darkorchid", "cyan4") ) + facet_grid(rows = vars(species)) + labs(title = "Penguin species differentation") + labs(subtitle = "based on bill depth and bill length") + * xlab("bill length (mm)") ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_06_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species2-auto[ ```r penguins_default + scale_color_manual( values = c("darkorange", "darkorchid", "cyan4") ) + facet_grid(rows = vars(species)) + labs(title = "Penguin species differentation") + labs(subtitle = "based on bill depth and bill length") + xlab("bill length (mm)") + * ylab("bill depth (mm)") ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_07_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species2-auto[ ```r penguins_default + scale_color_manual( values = c("darkorange", "darkorchid", "cyan4") ) + facet_grid(rows = vars(species)) + labs(title = "Penguin species differentation") + labs(subtitle = "based on bill depth and bill length") + xlab("bill length (mm)") + ylab("bill depth (mm)") + * theme_minimal() ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_08_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species2-auto[ ```r penguins_default + scale_color_manual( values = c("darkorange", "darkorchid", "cyan4") ) + facet_grid(rows = vars(species)) + labs(title = "Penguin species differentation") + labs(subtitle = "based on bill depth and bill length") + xlab("bill length (mm)") + ylab("bill depth (mm)") + theme_minimal() + * theme( * plot.title = * element_text(face = "bold"), * plot.subtitle = * element_text(face = "italic")) ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_09_output-1.png)<!-- --> ] --- count: false .panel1-penguins_species2-auto[ ```r penguins_default + scale_color_manual( values = c("darkorange", "darkorchid", "cyan4") ) + facet_grid(rows = vars(species)) + labs(title = "Penguin species differentation") + labs(subtitle = "based on bill depth and bill length") + xlab("bill length (mm)") + ylab("bill depth (mm)") + theme_minimal() + theme( plot.title = element_text(face = "bold"), plot.subtitle = element_text(face = "italic")) + * theme(legend.position = "none") ``` ] .panel2-penguins_species2-auto[ ``` ## `geom_smooth()` using formula 'y ~ x' ``` ![](prezentacja_JRom_2020-11-25_files/figure-html/penguins_species2_auto_10_output-1.png)<!-- --> ] <style> .panel1-penguins_species2-auto { color: black; width: 38.6060606060606%; hight: 32%; float: left; padding-left: 1%; font-size: 50% } .panel2-penguins_species2-auto { color: black; width: 59.3939393939394%; hight: 32%; float: left; padding-left: 1%; font-size: 50% } .panel3-penguins_species2-auto { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 50% } </style> ??? OK, to był podstawowy graf. Teraz zróbmy go wyjątkowego. - zmiana kolorystyki, - rozbicie na podgrafy wg.gatunku, - dodanie tytułu - podpisy na osiach - wygląd grafu --- ## tips and tricks - **kolory** - [ColorBrewer](https://colorbrewer2.org) wbudowane w ggplot2 [`scale_color_brewer`](https://ggplot2.tidyverse.org/reference/scale_brewer.html) - [sanzo palette](https://github.com/jmaasch/sanzo) można zainstalować z CRANa - mnóstwo innych możliwości: np. [paletteer](https://emilhvitfeldt.github.io/paletteer/) - **roszerzenia** - [ggrepel](https://ggrepel.slowkow.com/) ładniejsze pozycjonowanie napisów - [gggenes](https://wilkox.org/gggenes/) wizualizacja genów jako strzałek - mnóstwo innych możliwości: [ggextensions](https://exts.ggplot2.tidyverse.org/gallery/) ??? Jest mnóstwo innych pakietów, które pozwalają na dopasowanie naszych obrazków do naszego gustu. --- class: inverse, left, middle # Interaktywne grafy ## na szybko ??? Jednak na takim grafie przedstawimy tylko 2 dane: długość i szerokość dzioba pingwinów. Jeśli chcemy _jednocześnie_ pokazać inne dane, musimy zrobić więcej grafów, albo... spróbować dodać elementy interaktywne. --- <div style="float: right; position: fixed; right: 10px; top: 10px;"> <img style="float: right; position: relative;" src="ggiraph_logo.png" alt="ggiraph"/><br> </div> ## ggiraph https://davidgohel.github.io/ggiraph - do gotowego grafu `ggplot` dodaje interaktywność - rozszerza `ggplot2` o `geom`y: - `geom_point_interactive` - `geom_tile_interactive` - `scale_fill_manual_interactive` - i wiele więcej --- ```r penguins ``` ``` ## # A tibble: 344 x 8 ## species island bill_length_mm bill_depth_mm flipper_length_… body_mass_g ## <fct> <fct> <dbl> <dbl> <int> <int> ## 1 Adelie Torge… 39.1 18.7 181 3750 ## 2 Adelie Torge… 39.5 17.4 186 3800 ## 3 Adelie Torge… 40.3 18 195 3250 ## 4 Adelie Torge… NA NA NA NA ## 5 Adelie Torge… 36.7 19.3 193 3450 ## 6 Adelie Torge… 39.3 20.6 190 3650 ## 7 Adelie Torge… 38.9 17.8 181 3625 ## 8 Adelie Torge… 39.2 19.6 195 4675 ## 9 Adelie Torge… 34.1 18.1 193 3475 ## 10 Adelie Torge… 42 20.2 190 4250 ## # … with 334 more rows, and 2 more variables: sex <fct>, year <int> ``` --- ```r penguins_int <- penguins %>% mutate(hover_text = paste0("This ", sex, " lives at ", island, " and was measured in ", year)) penguins_int %>% select(hover_text) ``` ``` ## # A tibble: 344 x 1 ## hover_text ## <chr> ## 1 This male lives at Torgersen and was measured in 2007 ## 2 This female lives at Torgersen and was measured in 2007 ## 3 This female lives at Torgersen and was measured in 2007 ## 4 This NA lives at Torgersen and was measured in 2007 ## 5 This female lives at Torgersen and was measured in 2007 ## 6 This male lives at Torgersen and was measured in 2007 ## 7 This female lives at Torgersen and was measured in 2007 ## 8 This male lives at Torgersen and was measured in 2007 ## 9 This NA lives at Torgersen and was measured in 2007 ## 10 This NA lives at Torgersen and was measured in 2007 ## # … with 334 more rows ``` --- count: false .panel1-ggiraph_test-user[ ```r *penguins_int_plot <- ggplot( * data = penguins_int * ) + * aes(x = bill_length_mm, * y = bill_depth_mm) + * geom_point_interactive( #<< * aes(color = species, * shape = species, * tooltip = hover_text), #<< * size = 2) + * geom_smooth(method = "lm", * se = FALSE, * aes(color = species)) + * scale_color_manual( * values = c( * "darkorange", * "darkorchid", * "cyan4")) + * labs(title = * "Penguin species differentation") + * xlab("bill length (mm)") + * ylab("bill depth (mm)") + * theme_minimal() + * theme( * plot.title = * element_text(face = "bold"), * plot.subtitle = * element_text(face = "italic")) + * theme(legend.position = "bottom") ``` ] .panel2-ggiraph_test-user[ ] --- count: false .panel1-ggiraph_test-user[ ```r penguins_int_plot <- ggplot( data = penguins_int ) + aes(x = bill_length_mm, y = bill_depth_mm) + * geom_point_interactive( aes(color = species, shape = species, * tooltip = hover_text), size = 2) + geom_smooth(method = "lm", se = FALSE, aes(color = species)) + scale_color_manual( values = c( "darkorange", "darkorchid", "cyan4")) + labs(title = "Penguin species differentation") + xlab("bill length (mm)") + ylab("bill depth (mm)") + theme_minimal() + theme( plot.title = element_text(face = "bold"), plot.subtitle = element_text(face = "italic")) + theme(legend.position = "bottom") *girafe(ggobj = penguins_int_plot) ``` ] .panel2-ggiraph_test-user[ ``` ## `geom_smooth()` using formula 'y ~ x' ```
] <style> .panel1-ggiraph_test-user { color: black; width: 38.6060606060606%; hight: 32%; float: left; padding-left: 1%; font-size: 50% } .panel2-ggiraph_test-user { color: black; width: 59.3939393939394%; hight: 32%; float: left; padding-left: 1%; font-size: 50% } .panel3-ggiraph_test-user { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 50% } </style> --- <div style="float: right; position: fixed; right: 10px; top: 10px;"> <img style="float: right; position: relative;" src="plotly.png" alt="plotly"/><br> </div> ## ggplotly - [Plotly + ggplot2](https://plotly.com/ggplot2/) --- count: false .panel1-ggplotly_test-user[ ```r *penguins_int_plot <- ggplot( * data = penguins_int #<< * ) + * aes(x = bill_length_mm, * y = bill_depth_mm, * text = hover_text) + #<< * geom_point( * aes(color = species, * shape = species), * size = 2) + * scale_color_manual( * values = c( * "darkorange", * "darkorchid", * "cyan4")) + * labs(title = * "Penguin species differentation") + * xlab("bill length (mm)") + * ylab("bill depth (mm)") + * theme_minimal() + * theme(plot.title = * element_text(face = "bold")) ``` ] .panel2-ggplotly_test-user[ ] --- count: false .panel1-ggplotly_test-user[ ```r penguins_int_plot <- ggplot( * data = penguins_int ) + aes(x = bill_length_mm, y = bill_depth_mm, * text = hover_text) + geom_point( aes(color = species, shape = species), size = 2) + scale_color_manual( values = c( "darkorange", "darkorchid", "cyan4")) + labs(title = "Penguin species differentation") + xlab("bill length (mm)") + ylab("bill depth (mm)") + theme_minimal() + theme(plot.title = element_text(face = "bold")) *plotly::ggplotly( #<< * penguins_int_plot, #<< * tooltip = "text") ``` ] .panel2-ggplotly_test-user[
] <style> .panel1-ggplotly_test-user { color: black; width: 38.6060606060606%; hight: 32%; float: left; padding-left: 1%; font-size: 50% } .panel2-ggplotly_test-user { color: black; width: 59.3939393939394%; hight: 32%; float: left; padding-left: 1%; font-size: 50% } .panel3-ggplotly_test-user { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 50% } </style> --- class: inverse, left, middle # Interaktywne grafy ## zaawansowane ??? Chcecie jeszcze więcej? Proszę bardzo! --- <div style="float: right; position: fixed; right: 10px; top: 10px;"> <img style="float: right; position: relative;" src="highcharter_logo.png" alt="highcharter"/><br> </div> ## highcharter https://jkunst.com/highcharter/ - implementacja R biblioteki javascript [`highcharts`](https://www.highcharts.com/demo) - trochę jak ggplot: - dodajemy warstwy danych funkcją `hc_add_series` - dodajemy warstwy wizualne funkcją `hcaes` - szybkie rysowanie przez funkcję `hchart` - dodajemy elementy przez odpowiednie funkcje `hc_`, np. `hc_title` dodaje tytuł, `hc_colorAxis` definiuje paletę kolorów i dodaje legendę -- - mnóstwo przykładów: https://jkunst.com/highcharter/articles/showcase.html - bardziej zaawansowany przykład: https://jrom.bitbucket.io/showcase/ - kod: https://bitbucket.org/jrom/jrom.bitbucket.io/src/master/showcase/index.Rmd --- ## Interaktywny Rmarkdown - [flexdashboard](https://rmarkdown.rstudio.com/flexdashboard/index.html) - Rmarkdown z ekstra opcjami - dzięki `htmlwidgets` można łatwo umieszczać interaktywne komponenty - dzięki `crosstalk` można łączyć komponenty - [htmlwidgets](https://www.htmlwidgets.org/) - wybierz spośród gotowych funkcji R - kompilacja do JS i HTML - [crosstalk](https://rstudio.github.io/crosstalk/) - dodaj zależności pomiędzy komponentami --- ```yaml --- title: "Interactive results" output: flexdashboard::flex_dashboard: orientation: columns vertical_layout: scroll theme: paper --- Column {.tabset} ----------------------------------------------------------------------- ``{r} # twój kod z np. ggplotly `` ``` [Kliknij tu, żeby zobaczyć przykład](flexdashboard_penguins.html)