RWEP/SD/20240328_3_datavisualize/index.qmd

3939 lines
71 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "数据可视化"
subtitle: 《区域水环境污染数据分析实践》<br>Data analysis practice of regional water environment pollution
author: 苏命、王为东<br>中国科学院大学资源与环境学院<br>中国科学院生态环境研究中心
date: today
lang: zh
format:
revealjs:
theme: dark
slide-number: true
chalkboard:
buttons: true
preview-links: auto
lang: zh
toc: true
toc-depth: 1
toc-title: 大纲
logo: ./_extensions/inst/img/ucaslogo.png
css: ./_extensions/inst/css/revealjs.css
pointer:
key: "p"
color: "#32cd32"
pointerSize: 18
revealjs-plugins:
- pointer
filters:
- d2
knitr:
opts_chunk:
dev: "svg"
retina: 3
execute:
freeze: auto
cache: true
echo: true
fig-width: 5
fig-height: 6
---
```{r}
#| include: false
#| cache: false
knitr::opts_chunk$set(echo = TRUE)
source("../../coding/_common.R")
require(learnr)
library(tidyverse)
library(palmerpenguins)
library(ggthemes)
```
## {background-image="../../img/concepts/tidyverse-packages-ggplot.png" background-position="center" background-size="100%"}
## The ggplot2 Package
<br>
... is an **R package to visualize data** created by Hadley Wickham in 2005
```{r}
#| label: ggplot-package-install-2
#| eval: false
# install.packages("ggplot2")
library(ggplot2)
```
<br>
::: fragment
... is part of the [`{tidyverse}`](https://www.tidyverse.org/)
```{r}
#| label: tidyverse-package-install-2
#| eval: false
# install.packages("tidyverse")
library(tidyverse)
```
:::
# The Grammar of {ggplot2}
## The Grammar of {ggplot2}
<br>
<table style='width:100%;font-size:14pt;'>
<tr>
<th>Component</th>
<th>Function</th>
<th>Explanation</th>
</tr>
<tr>
<td><b style='color:#67676;'>Data</b></td>
<td><code>ggplot(data)</code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>*The raw data that you want to visualise.*</td>
</tr>
<tr>
<td><b style='color:#67676;'>Aesthetics&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></td>
<td><code>aes()</code></td>
<td>*Aesthetic mappings between variables and visual properties.*</td>
<tr>
<td><b style='color:#67676;'>Geometries</b></td>
<td><code>geom_*()</code></td>
<td>*The geometric shapes representing the data.*</td>
</tr>
</table>
## The Grammar of {ggplot2}
<br>
<table style='width:100%;font-size:14pt;'>
<tr>
<th>Component</th>
<th>Function</th>
<th>Explanation</th>
</tr>
<tr>
<td><b style='color:#67676;'>Data</b></td>
<td><code>ggplot(data)</code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>*The raw data that you want to visualise.*</td>
</tr>
<tr>
<td><b style='color:#67676;'>Aesthetics&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></td>
<td><code>aes()</code></td>
<td>*Aesthetic mappings between variables and visual properties.*</td>
<tr>
<td><b style='color:#67676;'>Geometries</b></td>
<td><code>geom_*()</code></td>
<td>*The geometric shapes representing the data.*</td>
</tr>
<tr>
<td><b style='color:#67676;'>Statistics</b></td>
<td><code>stat_*()</code></td>
<td>*The statistical transformations applied to the data.*</td>
</tr>
<tr>
<td><b style='color:#67676;'>Scales</b></td>
<td><code>scale_*()</code></td>
<td>*Maps between the data and the aesthetic dimensions.*</td>
</tr>
<tr>
<td><b style='color:#67676;'>Coordinate System</b></td>
<td><code>coord_*()</code></td>
<td>*Maps data into the plane of the data rectangle.*</td>
</tr>
<tr>
<td><b style='color:#67676;'>Facets</b></td>
<td><code>facet_*()</code></td>
<td>*The arrangement of the data into a grid of plots.*</td>
</tr>
<tr>
<td><b style='color:#67676;'>Visual Themes</b></td>
<td><code>theme() / theme_*()</code></td>
<td>*The overall visual defaults of a plot.*</td>
</tr>
</table>
## The Data
<b style='font-size:2.3rem;'>Bike sharing counts in London, UK, powered by [TfL Open Data](https://tfl.gov.uk/modes/cycling/santander-cycles)</b>
::: incremental
- covers the years 2015 and 2016
- incl. weather data acquired from [freemeteo.com](https://freemeteo.com)
- prepared by Hristo Mavrodiev for [Kaggle](https://www.kaggle.com/hmavrodiev/london-bike-sharing-dataset)
:::
<br>
::: fragment
```{r}
#| label: data-import
bikes <- readr::read_csv("../../data/ggplot2/london-bikes-custom.csv",
## or: "https://raw.githubusercontent.com/z3tt/graphic-design-ggplot2/main/data/london-bikes-custom.csv"
col_types = "Dcfffilllddddc"
)
bikes$season <- forcats::fct_inorder(bikes$season)
```
:::
------------------------------------------------------------------------
```{r}
#| label: data-table
#| echo: false
#| purl: false
library(tidyverse)
tibble(
Variable = names(bikes),
Description = c(
"Date encoded as `YYYY-MM-DD`", "`day` (6:00am5:59pm) or `night` (6:00pm5:59am)", "`2015` or `2016`", "`1` (January) to `12` (December)", "`winter`, `spring`, `summer`, or `autumn`", "Sum of reported bikes rented", "`TRUE` being Monday to Friday and no bank holiday", "`TRUE` being Saturday or Sunday", "`TRUE` being a bank holiday in the UK", "Average air temperature (°C)", "Average feels like temperature (°C)", "Average air humidity (%)", "Average wind speed (km/h)", "Most common weather type"
),
Class = c(
"date", "character", "factor", "factor", "factor", "integer", "logical", "logical", "logical", "double", "double", "double", "double", "character"
)
) %>%
kableExtra::kbl(
booktabs = TRUE, longtable = TRUE
) %>%
kableExtra::kable_styling(
font_size = 20
) %>%
kableExtra::kable_minimal(
"hover", full_width = TRUE, position = "left", html_font = "Spline Sans Mono"
)
```
## `ggplot2::ggplot()`
```{r}
#| label: ggplot-function
#| eval: false
#| echo: false
#?ggplot
```
![](../../img/concepts/ggplot-fun-help.png){fig-alt="The help page of the ggplot() function." fig-width="175%"}
## Data
```{r}
#| label: setup-ggplot-slides
#| include: false
#| purl: false
library(ggplot2)
theme_set(theme_grey(base_size = 14))
```
```{r}
#| label: ggplot-data
#| output-location: column
ggplot(data = bikes)
```
## Aesthetic Mapping视觉映射`aes(.)`
<br>
<b class='simple-highlight-grn' style='font-size:2.6rem;'>= link variables to graphical properties</b><br><br>
::: incremental
- positions (`x`, `y`)
- colors (`color`, `fill`)
- shapes (`shape`, `linetype`)
- size (`size`)
- transparency (`alpha`)
- groupings (`group`)
:::
## Aesthetic Mapping视觉映射`aes(.)`
```{r}
#| label: ggplot-aesthetics-outside
#| output-location: column
#| code-line-numbers: "2|1,2"
ggplot(data = bikes) +
aes(x = temp_feel, y = count)
```
## <span style='color:#4758AB;'>aes</span>thetics
`aes()` outside as component
```{r}
#| label: ggplot-aesthetics-outside-comp
#| eval: false
ggplot(data = bikes) +
aes(x = temp_feel, y = count)
```
<br>
::: fragment
`aes()` inside, explicit matching
```{r}
#| label: ggplot-aesthetics-inside
#| eval: false
ggplot(data = bikes, mapping = aes(x = temp_feel, y = count))
```
<br>
:::
::: fragment
`aes()` inside, implicit matching
```{r}
#| label: ggplot-aesthetics-inside-implicit
#| eval: false
ggplot(bikes, aes(temp_feel, count))
```
<br>
:::
::: fragment
`aes()` inside, mixed matching
```{r}
#| label: ggplot-aesthetics-inside-mix
#| eval: false
ggplot(bikes, aes(x = temp_feel, y = count))
```
:::
# Geometrical Layers
## Geometries几何图层geom_*
<br>
<b class='simple-highlight-grn' style='font-size:2.6rem;'>= interpret aesthetics as graphical representations</b><br><br>
::: incremental
- points
- lines
- polygons
- text labels
- ...
:::
## Geometries几何图层geom_*
```{r}
#| label: geom-point
#| output-location: column
#| code-line-numbers: "1,2,3,4|5"
ggplot(
bikes,
aes(x = temp_feel, y = count)
) +
geom_point()
```
## Visual Properties of Layers图层属性
```{r}
#| label: geom-point-properties
#| output-location: column
#| code-line-numbers: "5,6,7,8,9,10,11|6,7,8,9,10"
ggplot(
bikes,
aes(x = temp_feel, y = count)
) +
geom_point(
color = "#28a87d",
alpha = .5,
shape = "X",
stroke = 1,
size = 4
)
```
## Setting vs Mapping of Visual Properties
::: {layout-ncol="2"}
```{r}
#| label: geom-point-properties-set
#| fig-height: 3.5
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = temp_feel, y = count)
) +
geom_point(
color = "#28a87d",
alpha = .5
)
```
::: fragment
```{r}
#| label: geom-point-properties-map
#| fig-height: 3.5
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = temp_feel, y = count)
) +
geom_point(
aes(color = season),
alpha = .5
)
```
:::
:::
## Mapping Expressions
```{r}
#| label: geom-point-aes-expression
#| output-location: column
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = temp_feel, y = count)
) +
geom_point(
aes(color = temp_feel > 20),
alpha = .5
)
```
## Filter Data
```{r}
#| label: geom-point-aes-expression-exercise-na
#| output-location: column
#| code-line-numbers: "2"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = temp, y = temp_feel)
) +
geom_point(
aes(color = weather_type == "clear",
size = count),
shape = 18,
alpha = .5
)
```
## Filter Data
```{r}
#| label: geom-point-aes-expression-exercise-na-pipe
#| output-location: column
#| code-line-numbers: "2"
ggplot(
bikes %>% filter(!is.na(weather_type)),
aes(x = temp, y = temp_feel)
) +
geom_point(
aes(color = weather_type == "clear",
size = count),
shape = 18,
alpha = .5
)
```
```{r}
#| label: reset-theme
#| include: false
#| purl: false
theme_set(theme_grey(base_size = 14))
```
## Local vs. Global应用至当前图层或所有图层
::: {layout-ncol="2"}
```{r}
#| label: geom-point-aes-geom
#| code-line-numbers: "3,6"
#| fig-height: 3.2
ggplot(
bikes,
aes(x = temp_feel, y = count)
) +
geom_point(
aes(color = season),
alpha = .5
)
```
::: fragment
```{r}
#| label: geom-point-aes-global
#| code-line-numbers: "3,4"
#| fig-height: 3.2
ggplot(
bikes,
aes(x = temp_feel, y = count,
color = season)
) +
geom_point(
alpha = .5
)
```
:::
:::
## Adding More Layers
```{r}
#| label: geom-smooth
#| output-location: column
#| code-line-numbers: "9,10,11"
ggplot(
bikes,
aes(x = temp_feel, y = count,
color = season)
) +
geom_point(
alpha = .5
) +
geom_smooth(
method = "lm"
)
```
## Global Color Encoding
```{r}
#| label: geom-smooth-aes-global
#| output-location: column
#| code-line-numbers: "3,4,9,10,11"
ggplot(
bikes,
aes(x = temp_feel, y = count,
color = season)
) +
geom_point(
alpha = .5
) +
geom_smooth(
method = "lm"
)
```
## Local Color Encoding
```{r}
#| label: geom-smooth-aes-fixed
#| output-location: column
#| code-line-numbers: "6,9,10,11"
ggplot(
bikes,
aes(x = temp_feel, y = count)
) +
geom_point(
aes(color = season),
alpha = .5
) +
geom_smooth(
method = "lm"
)
```
## The \`group\` Aesthetic
```{r}
#| label: geom-smooth-aes-grouped
#| output-location: column
#| code-line-numbers: "10"
ggplot(
bikes,
aes(x = temp_feel, y = count)
) +
geom_point(
aes(color = season),
alpha = .5
) +
geom_smooth(
aes(group = day_night),
method = "lm"
)
```
## Set Both as Global Aesthetics
```{r}
#| label: geom-smooth-aes-global-grouped
#| output-location: column
#| code-line-numbers: "4,5"
ggplot(
bikes,
aes(x = temp_feel, y = count,
color = season,
group = day_night)
) +
geom_point(
alpha = .5
) +
geom_smooth(
method = "lm"
)
```
## Overwrite Global Aesthetics
```{r}
#| label: geom-smooth-aes-global-grouped-overwrite
#| output-location: column
#| code-line-numbers: "4,12"
ggplot(
bikes,
aes(x = temp_feel, y = count,
color = season,
group = day_night)
) +
geom_point(
alpha = .5
) +
geom_smooth(
method = "lm",
color = "black"
)
```
# Statistical Layers
## \`stat_\*()\` and \`geom_\*()\`
::: {layout-ncol="2"}
```{r}
#| label: stat-geom
#| fig-height: 5.1
#| code-line-numbers: "2"
ggplot(bikes, aes(x = temp_feel, y = count)) +
stat_smooth(geom = "smooth")
```
```{r}
#| label: geom-stat
#| fig-height: 5.1
#| code-line-numbers: "2"
ggplot(bikes, aes(x = temp_feel, y = count)) +
geom_smooth(stat = "smooth")
```
:::
## \`stat_\*()\` and \`geom_\*()\`
::: {layout-ncol="2"}
```{r}
#| label: stat-geom-2
#| fig-height: 5.1
#| code-line-numbers: "2"
ggplot(bikes, aes(x = season)) +
stat_count(geom = "bar")
```
```{r}
#| label: geom-stat-2
#| fig-height: 5.1
#| code-line-numbers: "2"
ggplot(bikes, aes(x = season)) +
geom_bar(stat = "count")
```
:::
## \`stat_\*()\` and \`geom_\*()\`
::: {layout-ncol="2"}
```{r}
#| label: stat-geom-3
#| fig-height: 5.1
#| code-line-numbers: "2"
ggplot(bikes, aes(x = date, y = temp_feel)) +
stat_identity(geom = "point")
```
```{r}
#| label: geom-stat-3
#| fig-height: 5.1
#| code-line-numbers: "2"
ggplot(bikes, aes(x = date, y = temp_feel)) +
geom_point(stat = "identity")
```
:::
## Statistical Summaries
```{r}
#| label: stat-summary
#| output-location: column
#| code-line-numbers: "5|3"
ggplot(
bikes,
aes(x = season, y = temp_feel)
) +
stat_summary()
```
## Statistical Summaries
```{r}
#| label: stat-summary-defaults
#| output-location: column
#| code-line-numbers: "6,7"
ggplot(
bikes,
aes(x = season, y = temp_feel)
) +
stat_summary(
fun.data = mean_se, ## the default
geom = "pointrange" ## the default
)
```
## Statistical Summaries
```{r}
#| label: stat-summary-median
#| output-location: column
#| code-line-numbers: "5|5,6,11|6,7,8,9,10,11|7,8"
ggplot(
bikes,
aes(x = season, y = temp_feel)
) +
geom_boxplot() +
stat_summary(
fun = mean,
geom = "point",
color = "#28a87d",
size = 3
)
```
## Statistical Summaries
```{r}
#| label: stat-summary-custom
#| output-location: column
#| code-line-numbers: "5,6,7,8,9|7,8"
ggplot(
bikes,
aes(x = season, y = temp_feel)
) +
stat_summary(
fun = mean,
fun.max = function(y) mean(y) + sd(y),
fun.min = function(y) mean(y) - sd(y)
)
```
# Extending a ggplot
## Store a ggplot as Object
```{r}
#| label: ggplot-object
#| code-line-numbers: "1,16"
g <-
ggplot(
bikes,
aes(x = temp_feel, y = count,
color = season,
group = day_night)
) +
geom_point(
alpha = .5
) +
geom_smooth(
method = "lm",
color = "black"
)
class(g)
```
## Inspect a ggplot Object
```{r}
#| label: ggplot-object-data
g$data
```
## Inspect a ggplot Object
```{r}
#| label: ggplot-object-mapping
g$mapping
```
## Extend a ggplot Object: Add Layers
```{r}
#| label: ggplot-object-extend-geom
#| output-location: column
g +
geom_rug(
alpha = .2
)
```
## Remove a Layer from the Legend
```{r}
#| label: geom-guide-none
#| output-location: column
#| code-line-numbers: "4"
g +
geom_rug(
alpha = .2,
show.legend = FALSE
)
```
## Extend a ggplot Object: Add Labels
```{r}
#| label: ggplot-labs-individual
#| output-location: column
#| code-line-numbers: "2,3,4"
g +
xlab("Feels-like temperature (°F)") +
ylab("Reported bike shares") +
ggtitle("TfL bike sharing trends")
```
## Extend a ggplot Object: Add Labels
```{r}
#| label: ggplot-labs-bundled
#| output-location: column
#| code-line-numbers: "2,3,4,5,6"
g +
labs(
x = "Feels-like temperature (°F)",
y = "Reported bike shares",
title = "TfL bike sharing trends"
)
```
## Extend a ggplot Object: Add Labels
```{r}
#| label: ggplot-labs-bundled-color
#| output-location: column
#| code-line-numbers: "6"
g <- g +
labs(
x = "Feels-like temperature (°F)",
y = "Reported bike shares",
title = "TfL bike sharing trends",
color = "Season:"
)
g
```
## Extend a ggplot Object: Add Labels
```{r}
#| label: ggplot-labs-bundled-extended
#| output-location: column
#| code-line-numbers: "6,7,9"
g +
labs(
x = "Feels-like temperature (°F)",
y = "Reported bike shares",
title = "TfL bike sharing trends",
subtitle = "Reported bike rents versus feels-like temperature in London",
caption = "Data: TfL",
color = "Season:",
tag = "Fig. 1"
)
```
## Extend a ggplot Object: Add Labels
::: {layout-ncol="2"}
```{r}
#| label: ggplot-labs-empty-vs-null-A
#| fig-height: 3.6
#| code-line-numbers: "3"
g +
labs(
x = "",
caption = "Data: TfL"
)
```
```{r}
#| label: ggplot-labs-empty-vs-null-B
#| fig-height: 3.6
#| code-line-numbers: "3"
g +
labs(
x = NULL,
caption = "Data: TfL"
)
```
:::
## Extend a ggplot Object: Themes
::: {layout-ncol="2"}
```{r}
#| label: ggplot-object-extend-theme-light
#| fig-height: 5.5
g + theme_light()
```
::: fragment
```{r}
#| label: ggplot-object-extend-theme-minimal
#| fig-height: 5.5
g + theme_minimal()
```
:::
:::
## Change the Theme Base Settings
```{r}
#| label: ggplot-theme-extend-theme-base
#| output-location: column
#| code-line-numbers: "2,3|1,2,3,4"
g + theme_light(
base_size = 14
)
```
## Set a Theme Globally
```{r}
#| label: ggplot-theme-global
#| output-location: column
theme_set(theme_light())
g
```
## Change the Theme Base Settings
```{r}
#| label: ggplot-theme-global-base
#| output-location: column
#| code-line-numbers: "2,3|1,2,3,4"
theme_set(theme_light(
base_size = 14
))
g
```
## Overwrite Specific Theme Settings
```{r}
#| label: ggplot-theme-settings-individual-1
#| output-location: column
#| code-line-numbers: "2|3"
g +
theme(
panel.grid.minor = element_blank()
)
```
## Overwrite Specific Theme Settings
```{r}
#| label: ggplot-theme-settings-individual-2
#| output-location: column
#| code-line-numbers: "4"
g +
theme(
panel.grid.minor = element_blank(),
plot.title = element_text(face = "bold")
)
```
## Overwrite Specific Theme Settings
```{r}
#| label: ggplot-theme-settings-individual-3
#| output-location: column
#| code-line-numbers: "5"
g +
theme(
panel.grid.minor = element_blank(),
plot.title = element_text(face = "bold"),
legend.position = "top"
)
```
## Overwrite Specific Theme Settings
```{r}
#| label: ggplot-theme-settings-individual-legend-none
#| output-location: column
#| code-line-numbers: "5"
g +
theme(
panel.grid.minor = element_blank(),
plot.title = element_text(face = "bold"),
legend.position = "none"
)
```
## Overwrite Specific Theme Settings
```{r}
#| label: ggplot-theme-settings-individual-4
#| output-location: column
#| code-line-numbers: "6|2,3,4,6,7"
g +
theme(
panel.grid.minor = element_blank(),
plot.title = element_text(face = "bold"),
legend.position = "top",
plot.title.position = "plot"
)
```
## Overwrite Theme Settings Globally
```{r}
#| label: ggplot-theme-settings-global
#| output-location: column
#| code-line-numbers: "1|2,3,4,5|1,2,3,4,5,6"
theme_update(
panel.grid.minor = element_blank(),
plot.title = element_text(face = "bold"),
legend.position = "top",
plot.title.position = "plot"
)
g
```
## Save the Graphic
```{r}
#| label: ggplot-save
#| eval: false
ggsave(g, filename = "my_plot.png")
```
::: fragment
```{r}
#| label: ggplot-save-implicit
#| eval: false
ggsave("my_plot.png")
```
:::
::: fragment
```{r}
#| label: ggplot-save-aspect
#| eval: false
ggsave("my_plot.png", width = 8, height = 5, dpi = 600)
```
:::
::: fragment
```{r}
#| label: ggplot-save-vector
#| eval: false
ggsave("my_plot.pdf", width = 20, height = 12, unit = "cm", device = cairo_pdf)
```
:::
::: fragment
```{r}
#| label: ggplot-save-cairo_pdf
#| eval: false
grDevices::cairo_pdf("my_plot.pdf", width = 10, height = 7)
g
dev.off()
```
:::
------------------------------------------------------------------------
<br>
![Modified from canva.com](../../img/concepts/vector-raster-canva.png){fig-alt="A comparison of vector and raster graphics." fig-width="150%"}
# Facets
## Facets
<br>
<b class='simple-highlight-grn' style='font-size:2.6rem;'>= split variables to multiple panels</b><br><br>
::: fragment
Facets are also known as:
- small multiples
- trellis graphs
- lattice plots
- conditioning
:::
------------------------------------------------------------------------
::: {layout-ncol="2"}
```{r}
#| label: facet-types-wrap
#| echo: false
#| purl: false
ggplot(bikes, aes(x = 1, y = 1)) +
geom_text(
aes(label = paste0("Subset for\n", stringr::str_to_title(season))),
size = 5, family = "Cabinet Grotesk", lineheight = .9
) +
facet_wrap(~stringr::str_to_title(season)) +
ggtitle("facet_wrap()") +
theme_bw(base_size = 24) +
theme(
plot.title = element_text(hjust = .5, family = "Tabular", face = "bold"),
strip.text = element_text(face = "bold", size = 18),
panel.grid = element_blank(),
axis.ticks = element_blank(),
axis.text = element_blank(),
axis.title = element_blank(),
plot.background = element_rect(color = "#f8f8f8", fill = "#f8f8f8"),
plot.margin = margin(t = 3, r = 25)
)
```
::: fragment
```{r}
#| label: facet-types-grid
#| echo: false
#| purl: false
data <- tibble(
x = 1, y = 1,
day_night = c("Day", "Day", "Night", "Night"),
year = factor(c("2015", "2016", "2015", "2016"), levels = levels(bikes$year)),
label = c("Subset for\nDay × 2015", "Subset for\nDay × 2016",
"Subset for\nNight × 2015", "Subset for\nNight × 2016")
)
ggplot(data, aes(x = 1, y = 1)) +
geom_text(
aes(label = label),
size = 5, family = "Cabinet Grotesk", lineheight = .9
) +
facet_grid(day_night ~ year) +
ggtitle("facet_grid()") +
theme_bw(base_size = 24) +
theme(
plot.title = element_text(hjust = .5, family = "Tabular", face = "bold"),
strip.text = element_text(face = "bold", size = 18),
panel.grid = element_blank(),
axis.ticks = element_blank(),
axis.text = element_blank(),
axis.title = element_blank(),
plot.background = element_rect(color = "#f8f8f8", fill = "#f8f8f8"),
plot.margin = margin(t = 3, l = 25)
)
```
:::
:::
## Setup
```{r}
#| label: theme-size-facets
#| include: false
#| purl: false
theme_set(theme_light(base_size = 12))
theme_update(
panel.grid.minor = element_blank(),
plot.title = element_text(face = "bold"),
legend.position = "top",
plot.title.position = "plot"
)
```
```{r}
#| label: facet-setup
#| output-location: column
#| code-line-numbers: "1,2,3,4,5,6,7,8,9,10|12"
g <-
ggplot(
bikes,
aes(x = temp_feel, y = count,
color = season)
) +
geom_point(
alpha = .3,
guide = "none"
)
g
```
## Wrapped Facets
```{r}
#| label: facet-wrap
#| output-location: column
#| code-line-numbers: "1,2,3,4|2,4|3"
g +
facet_wrap(
vars(day_night)
)
```
## Wrapped Facets
```{r}
#| label: facet-wrap-circumflex
#| output-location: column
#| code-line-numbers: "3"
g +
facet_wrap(
~ day_night
)
```
## Facet Multiple Variables
```{r}
#| label: facet-wrap-multiple
#| output-location: column
#| code-line-numbers: "3"
g +
facet_wrap(
~ is_workday + day_night
)
```
## Facet Options: Cols + Rows
```{r}
#| label: facet-wrap-options-ncol
#| output-location: column
#| code-line-numbers: "4"
g +
facet_wrap(
~ day_night,
ncol = 1
)
```
## Facet Options: Free Scaling
```{r}
#| label: facet-wrap-options-scales
#| output-location: column
#| code-line-numbers: "5"
g +
facet_wrap(
~ day_night,
ncol = 1,
scales = "free"
)
```
## Facet Options: Free Scaling
```{r}
#| label: facet-wrap-options-freey
#| output-location: column
#| code-line-numbers: "5"
g +
facet_wrap(
~ day_night,
ncol = 1,
scales = "free_y"
)
```
## Facet Options: Switch Labels
```{r}
#| label: facet-wrap-options-switch
#| output-location: column
#| code-line-numbers: "5"
g +
facet_wrap(
~ day_night,
ncol = 1,
switch = "x"
)
```
## Gridded Facets
```{r}
#| label: facet-grid
#| output-location: column
#| code-line-numbers: "2,5|3,4"
g +
facet_grid(
rows = vars(day_night),
cols = vars(is_workday)
)
```
## Gridded Facets
```{r}
#| label: facet-grid-circumflex
#| output-location: column
#| code-line-numbers: "3"
g +
facet_grid(
day_night ~ is_workday
)
```
## Facet Multiple Variables
```{r}
#| label: facet-grid-multiple
#| output-location: column
#| code-line-numbers: "3"
g +
facet_grid(
day_night ~ is_workday + season
)
```
## Facet Options: Free Scaling
```{r}
#| label: facet-grid-options-scales
#| output-location: column
#| code-line-numbers: "4"
g +
facet_grid(
day_night ~ is_workday,
scales = "free"
)
```
## Facet Options: Switch Labels
```{r}
#| label: facet-grid-options-switch
#| output-location: column
#| code-line-numbers: "5"
g +
facet_grid(
day_night ~ is_workday,
scales = "free",
switch = "y"
)
```
## Facet Options: Proportional Spacing
```{r}
#| label: facet-grid-options-space
#| output-location: column
#| code-line-numbers: "4,5|5"
g +
facet_grid(
day_night ~ is_workday,
scales = "free",
space = "free"
)
```
## Facet Options: Proportional Spacing
```{r}
#| label: facet-grid-options-space-y
#| output-location: column
#| code-line-numbers: "4,5"
g +
facet_grid(
day_night ~ is_workday,
scales = "free_y",
space = "free_y"
)
```
## Diamonds Facet
```{r}
#| label: diamonds-facet-start
#| output-location: column
#| code-line-numbers: "1,2,3,4,5,6,7,8,9,10,11,12|8,9,10"
ggplot(
diamonds,
aes(x = carat, y = price)
) +
geom_point(
alpha = .3
) +
geom_smooth(
method = "lm",
se = FALSE,
color = "dodgerblue"
)
```
## Diamonds Facet
```{r}
#| label: diamonds-facet
#| output-location: column
#| code-line-numbers: "13,14,15,16,17"
ggplot(
diamonds,
aes(x = carat, y = price)
) +
geom_point(
alpha = .3
) +
geom_smooth(
method = "lm",
se = FALSE,
color = "dodgerblue"
) +
facet_grid(
cut ~ clarity,
space = "free_x",
scales = "free_x"
)
```
## Diamonds Facet (Dark Theme Bonus)
```{r}
#| label: diamonds-facet-dark
#| output-location: column
#| code-line-numbers: "19,20,21,22"
ggplot(
diamonds,
aes(x = carat, y = price)
) +
geom_point(
alpha = .3,
color = "white"
) +
geom_smooth(
method = "lm",
se = FALSE,
color = "dodgerblue"
) +
facet_grid(
cut ~ clarity,
space = "free_x",
scales = "free_x"
) +
theme_dark(
base_size = 14
)
```
# Scales尺度
```{r}
#| label: theme-size-reset
#| include: false
#| purl: false
theme_set(theme_light(base_size = 14))
theme_update(
panel.grid.minor = element_blank(),
plot.title = element_text(face = "bold"),
legend.position = "top",
plot.title.position = "plot"
)
```
## Scales
<br>
<b class='simple-highlight-grn' style='font-size:2.6rem;'>= translate between variable ranges and property ranges</b><br><br>
::: incremental
- feels-like temperature  ⇄  x
- reported bike shares  ⇄  y
- season  ⇄  color
- year  ⇄  shape
- ...
:::
## Scales
The `scale_*()` components control the properties of all the<br><b class='simple-highlight-ylw'>aesthetic dimensions mapped to the data.</b>
<br>Consequently, there are `scale_*()` functions for all aesthetics such as:
- **positions** via `scale_x_*()` and `scale_y_*()`
- **colors** via `scale_color_*()` and `scale_fill_*()`
- **sizes** via `scale_size_*()` and `scale_radius_*()`
- **shapes** via `scale_shape_*()` and `scale_linetype_*()`
- **transparency** via `scale_alpha_*()`
## Scales
The `scale_*()` components control the properties of all the<br><b class='simple-highlight-ylw'>aesthetic dimensions mapped to the data.</b>
<br>The extensions (`*`) can be filled by e.g.:
- `continuous()`, `discrete()`, `reverse()`, `log10()`, `sqrt()`, `date()` for positions
- `continuous()`, `discrete()`, `manual()`, `gradient()`, `gradient2()`, `brewer()` for colors
- `continuous()`, `discrete()`, `manual()`, `ordinal()`, `area()`, `date()` for sizes
- `continuous()`, `discrete()`, `manual()`, `ordinal()` for shapes
- `continuous()`, `discrete()`, `manual()`, `ordinal()`, `date()` for transparency
------------------------------------------------------------------------
![Illustration by [Allison Horst](https://github.com/allisonhorst/stats-illustrations)](../../img/concepts/continuous_discrete.png){fig-size="120%" fig-align="center" fig-alt="Allison Horsts illustration ofthe correct use of continuous versus discrete; however, in {ggplot2} these are interpeted in a different way: as quantitative and qualitative."}
## Continuous vs. Discrete in {ggplot2}
::: {layout-ncol="2"}
## Continuous:<br>quantitative or numerical data
- height
- weight
- age
- counts
## Discrete:<br>qualitative or categorical data
- species
- sex
- study sites
- age group
:::
## Continuous vs. Discrete in {ggplot2}
::: {layout-ncol="2"}
## Continuous:<br>quantitative or numerical data
- height (continuous)
- weight (continuous)
- age (continuous or discrete)
- counts (discrete)
## Discrete:<br>qualitative or categorical data
- species (nominal)
- sex (nominal)
- study site (nominal or ordinal)
- age group (ordinal)
:::
## Aesthetics + Scales
```{r}
#| label: scales-default-invisible
#| output-location: column
#| code-line-numbers: "3,4"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point()
```
## Aesthetics + Scales
```{r}
#| label: scales-default
#| output-location: column
#| code-line-numbers: "3,4,7,8,9|7,8,9"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_x_date() +
scale_y_continuous() +
scale_color_discrete()
```
## Scales
```{r}
#| label: scales-overwrite-1
#| output-location: column
#| code-line-numbers: "7"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_x_continuous() +
scale_y_continuous() +
scale_color_discrete()
```
## Scales
```{r}
#| label: scales-overwrite-2
#| output-location: column
#| code-line-numbers: "8"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_x_continuous() +
scale_y_log10() +
scale_color_discrete()
```
## Scales
```{r}
#| label: scales-overwrite-3
#| output-location: column
#| code-line-numbers: "9"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_x_continuous() +
scale_y_log10() +
scale_color_viridis_d()
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-trans
#| output-location: column
#| code-line-numbers: "8,9,10|9"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
trans = "log10"
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-name
#| output-location: column
#| code-line-numbers: "7,8,9|8"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares"
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-breaks-seq
#| output-location: column
#| code-line-numbers: "9"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares",
breaks = seq(0, 60000, by = 15000)
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-breaks-short
#| output-location: column
#| code-line-numbers: "9"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares",
breaks = 0:4*15000
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-breaks-irregular
#| output-location: column
#| code-line-numbers: "9"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares",
breaks = c(0, 2:12*2500, 40000, 50000)
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-labels
#| output-location: column
#| code-line-numbers: "8,10"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares in thousands",
breaks = 0:4*15000,
labels = 0:4*15
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-labels-paste
#| output-location: column
#| code-line-numbers: "10"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares in thousands",
breaks = 0:4*15000,
labels = paste(0:4*15000, "bikes")
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-limits
#| output-location: column
#| code-line-numbers: "10"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares",
breaks = 0:4*15000,
limits = c(NA, 60000)
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-expand.no
#| output-location: column
#| code-line-numbers: "10"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares",
breaks = 0:4*15000,
expand = c(0, 0)
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-expand
#| output-location: column
#| code-line-numbers: "10"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares",
breaks = -1:5*15000,
expand = c(.5, .5) ## c(add, mult)
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-expand-add-explicit
#| output-location: column
#| code-line-numbers: "10"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares",
breaks = -1:5*15000,
expand = expansion(add = 2000)
)
```
## \`scale_x\|y_continuous\`
```{r}
#| label: scales-xy-continuous-guide-none
#| output-location: column
#| code-line-numbers: "10"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_y_continuous(
name = "Reported bike shares",
breaks = 0:4*15000,
guide = "none"
)
```
## \`scale_x\|y_date\`
```{r}
#| label: scales-xy-date-breaks-months
#| output-location: column
#| code-line-numbers: "7,10|7,8,9,10|9"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_x_date(
name = NULL,
date_breaks = "4 months"
)
```
## \`scale_x\|y_date\`
```{r}
#| label: scales-xy-date-breaks-weeks
#| output-location: column
#| code-line-numbers: "9"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_x_date(
name = NULL,
date_breaks = "20 weeks"
)
```
## \`scale_x\|y_date\` with \`strftime()\`
```{r}
#| label: scales-xy-date-labels
#| output-location: column
#| code-line-numbers: "9,10"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_x_date(
name = NULL,
date_breaks = "6 months",
date_labels = "%Y/%m/%d"
)
```
## \`scale_x\|y_date\` with \`strftime()\`
```{r}
#| label: scales-xy-date-labels-special
#| output-location: column
#| code-line-numbers: "10"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_x_date(
name = NULL,
date_breaks = "6 months",
date_labels = "%b '%y"
)
```
## \`scale_x\|y_discrete\`
```{r}
#| label: scales-xy-discrete
#| output-location: column
#| code-line-numbers: "3,6,9|6,7,8,9|7,8"
ggplot(
bikes,
aes(x = season, y = count)
) +
geom_boxplot() +
scale_x_discrete(
name = "Period",
labels = c("Dec-Feb", "Mar-May", "Jun-Aug", "Sep-Nov")
)
```
## \`scale_x\|y_discrete\`
```{r}
#| label: scales-xy-discrete-expand
#| output-location: column
#| code-line-numbers: "8"
ggplot(
bikes,
aes(x = season, y = count)
) +
geom_boxplot() +
scale_x_discrete(
name = "Season",
expand = c(.5, 0) ## add, mult
)
```
## Discrete or Continuous?
```{r}
#| label: scales-xy-fake-discrete-visible
#| output-location: column
#| code-line-numbers: "3,5,6,7"
ggplot(
bikes,
aes(x = as.numeric(season), y = count)
) +
geom_boxplot(
aes(group = season)
)
```
## Discrete or Continuous?
```{r}
#| label: scales-xy-fake-discrete
#| output-location: column
#| code-line-numbers: "9,10,11,12,13|11|12"
ggplot(
bikes,
aes(x = as.numeric(season),
y = count)
) +
geom_boxplot(
aes(group = season)
) +
scale_x_continuous(
name = "Season",
breaks = 1:4,
labels = levels(bikes$season)
)
```
## Discrete or Continuous?
```{r}
#| label: scales-xy-fake-discrete-shift
#| output-location: column
#| code-line-numbers: "3,4"
ggplot(
bikes,
aes(x = as.numeric(season) +
as.numeric(season) / 8,
y = count)
) +
geom_boxplot(
aes(group = season)
) +
scale_x_continuous(
name = "Season",
breaks = 1:4,
labels = levels(bikes$season)
)
```
## \`scale_color\|fill_discrete\`
```{r}
#| label: scales-color-discrete-type-vector
#| output-location: column
#| code-line-numbers: "7,10|7,8,9,10|8,9"
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_color_discrete(
name = "Season:",
type = c("#69b0d4", "#00CB79", "#F7B01B", "#a78f5f")
)
```
## Inspect Assigned Colors
```{r}
#| label: scales-color-discrete-type-inspect
#| output-location: column
#| code-line-numbers: "1|12|14"
g <- ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_color_discrete(
name = "Season:",
type = c("#3ca7d9", "#1ec99b", "#F7B01B", "#bb7e8f")
)
gb <- ggplot_build(g)
gb$data[[1]][c(1:5, 200:205, 400:405), 1:5]
```
## \`scale_color\|fill_discrete\`
```{r}
#| label: scales-color-discrete-type-vector-named
#| output-location: column
#| code-line-numbers: "1,2,3,4,5,6|1,16"
my_colors <- c(
`winter` = "#3c89d9",
`spring` = "#1ec99b",
`summer` = "#F7B01B",
`autumn` = "#a26e7c"
)
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_color_discrete(
name = "Season:",
type = my_colors
)
```
## \`scale_color\|fill_discrete\`
```{r}
#| label: scales-color-discrete-type-vector-named-shuffled
#| output-location: column
#| code-line-numbers: "2,5|1,16"
my_colors_alphabetical <- c(
`autumn` = "#a26e7c",
`spring` = "#1ec99b",
`summer` = "#F7B01B",
`winter` = "#3c89d9"
)
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_color_discrete(
name = "Season:",
type = my_colors_alphabetical
)
```
## \`scale_color\|fill_discrete\`
```{r}
#| label: scales-color-discrete-type-palette
#| output-location: column
#| code-line-numbers: "1|11,12,13"
library(RColorBrewer)
ggplot(
bikes,
aes(x = date, y = count,
color = season)
) +
geom_point() +
scale_color_discrete(
name = "Season:",
type = brewer.pal(
n = 4, name = "Dark2"
)
)
```
## \`scale_color\|fill_manual\`
```{r}
#| label: scales-color-manual-na
#| output-location: column
#| code-line-numbers: "4,9,10"
ggplot(
bikes,
aes(x = date, y = count,
color = weather_type)
) +
geom_point() +
scale_color_manual(
name = "Season:",
values = brewer.pal(n = 6, name = "Pastel1"),
na.value = "black"
)
```
## \`scale_color\|fill_carto_d\`
```{r}
#| label: scales-color-discrete-carto
#| output-location: column
#| code-line-numbers: "7,8,9,10"
ggplot(
bikes,
aes(x = date, y = count,
color = weather_type)
) +
geom_point() +
rcartocolor::scale_color_carto_d(
name = "Season:",
palette = "Pastel",
na.value = "black"
)
```
## Diamonds Facet
```{r}
#| label: diamonds-facet-store
#| output-location: column
#| code-line-numbers: "1|10|20"
facet <-
ggplot(
diamonds,
aes(x = carat, y = price)
) +
geom_point(
alpha = .3
) +
geom_smooth(
aes(color = cut),
method = "lm",
se = FALSE
) +
facet_grid(
cut ~ clarity,
space = "free_x",
scales = "free_x"
)
facet
```
## Diamonds Facet
```{r}
#| label: diamonds-facet-scales-xy
#| output-location: column
facet +
scale_x_continuous(
breaks = 0:5
) +
scale_y_continuous(
limits = c(0, 30000),
breaks = 0:3*10000,
labels = c("$0", "$10,000", "$20,000", "$30,000")
)
```
## Diamonds Facet
```{r}
#| label: diamonds-facet-scales-y-paste-format
#| output-location: column
#| code-line-numbers: "8,9,10,11,12,13,14"
facet +
scale_x_continuous(
breaks = 0:5
) +
scale_y_continuous(
limits = c(0, 30000),
breaks = 0:3*10000,
labels = paste0(
"$", format(
0:3*10000,
big.mark = ",",
trim = TRUE
)
)
)
```
## Diamonds Facet
```{r}
#| label: diamonds-facet-scales-y-function
#| output-location: column
#| code-line-numbers: "8,9,10,11,12,13"
facet +
scale_x_continuous(
breaks = 0:5
) +
scale_y_continuous(
limits = c(0, 30000),
breaks = 0:3*10000,
labels = function(y) paste0(
"$", format(
y, big.mark = ",",
trim = TRUE
)
)
)
```
## Diamonds Facet
```{r}
#| label: diamonds-facet-scales-y-dollar-format
#| output-location: column
#| code-line-numbers: "8"
facet +
scale_x_continuous(
breaks = 0:5
) +
scale_y_continuous(
limits = c(0, 30000),
breaks = 0:3*10000,
labels = scales::dollar_format()
)
```
## Diamonds Facet
```{r}
#| label: diamonds-facet-scales-color
#| output-location: column
#| code-line-numbers: "10,11,12,13"
facet +
scale_x_continuous(
breaks = 0:5
) +
scale_y_continuous(
limits = c(0, 30000),
breaks = 0:3*10000,
labels = scales::dollar_format()
) +
scale_color_brewer(
palette = "Set2",
guide = "none"
)
```
## Diamonds Facet
```{r}
#| label: diamonds-facet-scales-no-legend
#| output-location: column
#| code-line-numbers: "13,14,15"
facet +
scale_x_continuous(
breaks = 0:5
) +
scale_y_continuous(
limits = c(0, 30000),
breaks = 0:3*10000,
labels = scales::dollar_format()
) +
scale_color_brewer(
palette = "Set2"
) +
theme(
legend.position = "none"
)
```
# Coordinate Systems投影
## Coordinate Systems
<br>
<b class='simple-highlight-grn' style='font-size:2.6rem;'>= interpret the position aesthetics</b><br><br>
::: incremental
- **linear coordinate systems:** preserve the geometrical shapes
- `coord_cartesian()`
- `coord_fixed()`
- `coord_flip()`
- **non-linear coordinate systems:** likely change the geometrical shapes
- `coord_polar()`
- `coord_map()` and `coord_sf()`
- `coord_trans()`
:::
## Cartesian Coordinate System
```{r}
#| label: coord-cartesian
#| output-location: column
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = season, y = count)
) +
geom_boxplot() +
coord_cartesian()
```
## Cartesian Coordinate System
```{r}
#| label: coord-cartesian-zoom
#| output-location: column
#| code-line-numbers: "6,7,8"
ggplot(
bikes,
aes(x = season, y = count)
) +
geom_boxplot() +
coord_cartesian(
ylim = c(NA, 15000)
)
```
## Changing Limits
::: {layout-ncol="2"}
```{r}
#| label: coord-cartesian-ylim
#| fig-height: 3.5
#| code-line-numbers: "6,7,8"
ggplot(
bikes,
aes(x = season, y = count)
) +
geom_boxplot() +
coord_cartesian(
ylim = c(NA, 15000)
)
```
```{r}
#| label: scale-y-limits
#| fig-height: 3.5
#| code-line-numbers: "6,7,8"
ggplot(
bikes,
aes(x = season, y = count)
) +
geom_boxplot() +
scale_y_continuous(
limits = c(NA, 15000)
)
```
:::
## Clipping
```{r}
#| label: coord-clip
#| output-location: column
#| code-line-numbers: "8"
ggplot(
bikes,
aes(x = season, y = count)
) +
geom_boxplot() +
coord_cartesian(
ylim = c(NA, 15000),
clip = "off"
)
```
## Clipping
```{r}
#| label: coord-clip-text
#| output-location: column
#| code-line-numbers: "2,3|6,7,8,9,10|12"
ggplot(
filter(bikes, is_holiday == TRUE),
aes(x = temp_feel, y = count)
) +
geom_point() +
geom_text(
aes(label = season),
nudge_x = .3,
hjust = 0
) +
coord_cartesian(
clip = "off"
)
```
## ... or better use {ggrepel}
```{r}
#| label: coord-clip-text-repel
#| output-location: column
#| code-line-numbers: "6"
ggplot(
filter(bikes, is_holiday == TRUE),
aes(x = temp_feel, y = count)
) +
geom_point() +
ggrepel::geom_text_repel(
aes(label = season),
nudge_x = .3,
hjust = 0
) +
coord_cartesian(
clip = "off"
)
```
## Remove All Padding
```{r}
#| label: coord-expand-off-clip
#| output-location: column
#| code-line-numbers: "7|8"
ggplot(
bikes,
aes(x = temp_feel, y = count)
) +
geom_point() +
coord_cartesian(
expand = FALSE,
clip = "off"
)
```
## Fixed Coordinate System
::: {layout-ncol="2"}
```{r}
#| label: coord-fixed
#| fig-height: 4.2
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = temp_feel, y = temp)
) +
geom_point() +
coord_fixed()
```
::: fragment
```{r}
#| label: coord-fixed-custom
#| fig-height: 4.2
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = temp_feel, y = temp)
) +
geom_point() +
coord_fixed(ratio = 4)
```
:::
:::
## Flipped Coordinate System
::: {layout-ncol="2"}
```{r}
#| label: coord-cartesian-comp-flip
#| fig-height: 4.1
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = weather_type)
) +
geom_bar() +
coord_cartesian()
```
```{r}
#| label: coord-flip
#| fig-height: 4.1
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = weather_type)
) +
geom_bar() +
coord_flip()
```
:::
## Flipped Coordinate System
::: {layout-ncol="2"}
```{r}
#| label: coord-cartesian-switch-x-y
#| fig-height: 4.1
#| code-line-numbers: "3,6"
ggplot(
bikes,
aes(y = weather_type)
) +
geom_bar() +
coord_cartesian()
```
```{r}
#| label: coord-flip-again
#| fig-height: 4.1
#| code-line-numbers: "3,6"
ggplot(
bikes,
aes(x = weather_type)
) +
geom_bar() +
coord_flip()
```
:::
## Reminder: Sort Your Bars!
```{r}
#| label: forcats-sort-infreq
#| output-location: column
#| code-line-numbers: "3|2"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(y = fct_infreq(weather_type))
) +
geom_bar()
```
## Reminder: Sort Your Bars!
```{r}
#| label: forcats-sort-infreq-rev
#| output-location: column
#| code-line-numbers: "3,4,5"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(y = fct_rev(
fct_infreq(weather_type)
))
) +
geom_bar()
```
## Circular Corrdinate System
::: {layout-ncol="2"}
```{r}
#| label: coord-polar
#| fig-height: 3.9
#| code-line-numbers: "7"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = weather_type,
fill = weather_type)
) +
geom_bar() +
coord_polar()
```
::: fragment
```{r}
#| label: coord-cartesian-comp-polar
#| fig-height: 3.9
#| code-line-numbers: "7"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = weather_type,
fill = weather_type)
) +
geom_bar() +
coord_cartesian()
```
:::
:::
## Circular Cordinate System
::: {layout-ncol="2"}
```{r}
#| label: coord-polar-coxcomb
#| fig-height: 3.9
#| code-line-numbers: "6,7"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = fct_infreq(weather_type),
fill = weather_type)
) +
geom_bar(width = 1) +
coord_polar()
```
```{r}
#| label: coord-cartesian-comp-polar-no-padding
#| fig-height: 3.9
#| code-line-numbers: "6,7"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = fct_infreq(weather_type),
fill = weather_type)
) +
geom_bar(width = 1) +
coord_cartesian()
```
:::
## Circular Corrdinate System
::: {layout-ncol="2"}
```{r}
#| label: coord-polar-theta-x
#| fig-height: 3.9
#| code-line-numbers: "7"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = fct_infreq(weather_type),
fill = weather_type)
) +
geom_bar() +
coord_polar(theta = "x")
```
```{r}
#| label: coord-polar-theta-y
#| fig-height: 3.9
#| code-line-numbers: "7"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = fct_infreq(weather_type),
fill = weather_type)
) +
geom_bar() +
coord_polar(theta = "y")
```
:::
## Circular Corrdinate System
::: {layout-ncol="2"}
```{r}
#| label: coord-polar-pie
#| fig-height: 4.1
#| code-line-numbers: "5"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = 1, fill = weather_type)
) +
geom_bar(position = "stack") +
coord_polar(theta = "y")
```
```{r}
#| label: coord-cartesian-comp-polar-stacked
#| fig-height: 4.1
#| code-line-numbers: "5"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = 1, fill = weather_type)
) +
geom_bar(position = "stack") +
coord_cartesian()
```
:::
## Circular Corrdinate System
::: {layout-ncol="2"}
```{r}
#| label: coord-polar-pie-sorted
#| fig-height: 3.6
#| code-line-numbers: "4,6,7"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = 1,
fill = fct_rev(fct_infreq(weather_type)))
) +
geom_bar(position = "stack") +
coord_polar(theta = "y") +
scale_fill_discrete(name = NULL)
```
```{r}
#| label: coord-cartesian-comp-polar-stacked-sorted
#| fig-height: 3.6
#| code-line-numbers: "4,6,7"
ggplot(
filter(bikes, !is.na(weather_type)),
aes(x = 1,
fill = fct_rev(fct_infreq(weather_type)))
) +
geom_bar(position = "stack") +
coord_cartesian() +
scale_fill_discrete(name = NULL)
```
:::
## Transform a Coordinate System
```{r}
#| label: coord-trans-log
#| output-location: column
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = temp, y = count)
) +
geom_point() +
coord_trans(y = "log10")
```
## Transform a Coordinate System
::: {layout-ncol="2"}
```{r}
#| label: trans-log-via-coord
#| fig-height: 3.6
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = temp, y = count,
group = day_night)
) +
geom_point() +
geom_smooth(method = "lm") +
coord_trans(y = "log10")
```
::: fragment
```{r}
#| label: trans-log-via-scale
#| fig-height: 3.6
#| code-line-numbers: "6"
ggplot(
bikes,
aes(x = temp, y = count,
group = day_night)
) +
geom_point() +
geom_smooth(method = "lm") +
scale_y_log10()
```
:::
:::
# 图形组合
------------------------------------------------------------------------
![Illustration by [Allison Horst](https://github.com/allisonhorst/stats-illustrations)](../../img/layout/ah_patchwork.jpg){fig-align="center" fig-alt="Allison Horsts monster illustration of the patchwork extension package."}
::: footer
:::
------------------------------------------------------------------------
::: panel-tabset
### Graphic
```{r}
#| label: patchwork-p1
#| fig-width: 10
#| fig-height: 5.8
#| echo: false
theme_std <- theme_set(theme_minimal(base_size = 18))
theme_update(
# text = element_text(family = "Pally"),
panel.grid = element_blank(),
axis.text = element_text(color = "grey50", size = 12),
axis.title = element_text(color = "grey40", face = "bold"),
axis.title.x = element_text(margin = margin(t = 12)),
axis.title.y = element_text(margin = margin(r = 12)),
axis.line = element_line(color = "grey80", size = .4),
legend.text = element_text(color = "grey50", size = 12),
plot.tag = element_text(size = 40, margin = margin(b = 15)),
plot.background = element_rect(fill = "white", color = "white")
)
bikes_sorted <-
bikes %>%
filter(!is.na(weather_type)) %>%
group_by(weather_type) %>%
mutate(sum = sum(count)) %>%
ungroup() %>%
mutate(
weather_type = forcats::fct_reorder(
str_to_title(str_wrap(weather_type, 5)), sum
)
)
p1 <- ggplot(
bikes_sorted,
aes(x = weather_type, y = count, color = weather_type)
) +
geom_hline(yintercept = 0, color = "grey80", size = .4) +
stat_summary(
geom = "point", fun = "sum", size = 12
) +
stat_summary(
geom = "linerange", ymin = 0, fun.max = function(y) sum(y),
size = 2, show.legend = FALSE
) +
coord_flip(ylim = c(0, NA), clip = "off") +
scale_y_continuous(
expand = c(0, 0), limits = c(0, 8500000),
labels = scales::comma_format(scale = .0001, suffix = "K")
) +
scale_color_viridis_d(
option = "magma", direction = -1, begin = .1, end = .9, name = NULL,
guide = guide_legend(override.aes = list(size = 7))
) +
labs(
x = NULL, y = "Sum of reported bike shares", tag = "P1",
) +
theme(
axis.line.y = element_blank(),
axis.text.y = element_text(family = "Pally", color = "grey50", face = "bold",
margin = margin(r = 15), lineheight = .9)
)
p1
```
### Code
```{r}
#| label: patchwork-p1
#| eval: false
```
:::
------------------------------------------------------------------------
::: panel-tabset
### Graphic
```{r}
#| label: patchwork-p2
#| fig-width: 10
#| fig-height: 5.8
#| echo: false
p2 <- bikes_sorted %>%
filter(season == "winter", is_weekend == TRUE, day_night == "night") %>%
group_by(weather_type, .drop = FALSE) %>%
mutate(id = row_number()) %>%
ggplot(
aes(x = weather_type, y = id, color = weather_type)
) +
geom_point(size = 4.5) +
scale_color_viridis_d(
option = "magma", direction = -1, begin = .1, end = .9, name = NULL,
guide = guide_legend(override.aes = list(size = 7))
) +
labs(
x = NULL, y = "Reported bike shares on\nweekend winter nights", tag = "P2",
) +
coord_cartesian(ylim = c(.5, NA), clip = "off")
p2
```
### Code
```{r}
#| label: patchwork-p2
#| eval: false
```
:::
------------------------------------------------------------------------
::: panel-tabset
### Graphic
```{r}
#| label: patchwork-p3
#| fig-width: 10
#| fig-height: 5.8
#| echo: false
my_colors <- c("#cc0000", "#000080")
p3 <- bikes %>%
group_by(week = lubridate::week(date), day_night, year) %>%
summarize(count = sum(count)) %>%
group_by(week, day_night) %>%
mutate(avg = mean(count)) %>%
ggplot(aes(x = week, y = count, group = interaction(day_night, year))) +
geom_line(color = "grey65", size = 1) +
geom_line(aes(y = avg, color = day_night), stat = "unique", size = 1.7) +
annotate(
geom = "text", label = c("Day", "Night"), color = my_colors,
x = c(5, 18), y = c(125000, 29000), size = 8, fontface = "bold", family = "Pally"
) +
scale_x_continuous(breaks = c(1, 1:10*5)) +
scale_y_continuous(labels = scales::comma_format()) +
scale_color_manual(values = my_colors, guide = "none") +
labs(
x = "Week of the Year", y = "Reported bike shares\n(cumulative # per week)", tag = "P3",
)
p3
```
### Code
```{r}
#| label: patchwork-p3
#| eval: false
```
:::
## {patchwork}
```{r}
#| label: patchwork-composition
#| fig-width: 15
#| fig-height: 12
#| fig-align: "center"
#| code-line-numbers: "3|2,3"
# install.packages("patchwork")
require(patchwork)
(p1 + p2) / p3
```
## "Collect Guides"
```{r}
#| label: patchwork-composition-guides
#| fig-width: 15
#| fig-height: 12
#| fig-align: "center"
(p1 + p2) / p3 + plot_layout(guides = "collect")
```
## Apply Theming
```{r}
#| label: patchwork-composition-guides-just
#| fig-width: 15
#| fig-height: 12
#| fig-align: "center"
((p1 + p2) / p3 & theme(legend.justification = "top")) +
plot_layout(guides = "collect")
```
## Apply Theming
```{r}
#| label: patchwork-composition-legend-off
#| fig-width: 15
#| fig-height: 12
#| fig-align: "center"
(p1 + p2) / p3 & theme(legend.position = "none",
plot.background = element_rect(color = "black", size = 3))
```
## Adjust Widths and Heights
```{r}
#| label: patchwork-composition-heights-widths
#| fig-width: 15
#| fig-height: 12
#| fig-align: "center"
#| code-line-numbers: "2"
((p1 + p2) / p3 & theme(legend.position = "none")) +
plot_layout(heights = c(.2, .1), widths = c(2, 1))
```
## Use A Custom Layout
```{r}
#| label: patchwork-composition-design
#| fig-width: 15
#| fig-height: 12
#| fig-align: "center"
#| code-line-numbers: "1,2,3,4|5"
picasso <- "
AAAAAA#BBBB
CCCCCCCCC##
CCCCCCCCC##"
(p1 + p2 + p3 & theme(legend.position = "none")) +
plot_layout(design = picasso)
```
## Add Labels
```{r}
#| label: patchwork-composition-labs-prep
pl1 <- p1 + labs(tag = NULL, title = "Plot One") + theme(legend.position = "none")
pl2 <- p2 + labs(tag = NULL, title = "Plot Two") + theme(legend.position = "none")
pl3 <- p3 + labs(tag = NULL, title = "Plot Three") + theme(legend.position = "none")
```
## Add Labels
```{r}
#| label: patchwork-composition-labs
#| fig-width: 15
#| fig-height: 12
#| fig-align: "center"
#| code-line-numbers: "2"
(pl1 + pl2) / pl3 +
plot_annotation(tag_levels = "1",
tag_prefix = "P",
title = "An overarching title for all 3 plots, placed on the very top while all other titles are sitting below the tags.")
```
## Add Text
::: panel-tabset
### Graphic
```{r}
#| label: patchwork-composition-textbox-prep
#| echo: false
#| fig-width: 9
#| fig-height: 4.5
#| fig-align: "center"
text <- tibble::tibble(
x = 0, y = 0, label = "Lorem ipsum dolor sit amet, **consectetur adipiscing elit**, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation <b style='color:#000080;'>ullamco laboris nisi</b> ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat <b style='color:#cc0000;'>cupidatat non proident</b>, sunt in culpa qui officia deserunt mollit anim id est laborum."
)
pt <- ggplot(text, aes(x = x, y = y)) +
ggtext::geom_textbox(
aes(label = label),
box.color = NA, width = unit(23, "lines"),
color = "grey40", size = 6.5, lineheight = 1.4
) +
coord_cartesian(expand = FALSE, clip = "off") +
theme_void()
pt
```
### Code
```{r}
#| label: patchwork-composition-textbox-prep
#| eval: false
```
:::
## Add Text
```{r}
#| label: patchwork-composition-textbox
#| fig-width: 15
#| fig-height: 12
#| fig-align: "center"
(p1 + pt) / p3
```
## Add Inset Plots
```{r}
#| label: patchwork-composition-inset-1
#| fig-width: 12
#| fig-height: 7
#| fig-align: "center"
pl1 + inset_element(pl2,
l = .6, b = .1, r = 1, t = .6)
```
## Add Inset Plots
```{r}
#| label: patchwork-composition-inset-2
#| fig-width: 12
#| fig-height: 7
#| fig-align: "center"
pl1 + inset_element(pl2,
l = .6, b = 0, r = 1, t = .5, align_to = 'full')
```
## Add Inset Plots
```{r}
#| label: patchwork-composition-inset-3
#| fig-width: 15
#| fig-height: 12
#| fig-align: "center"
(pl1 + inset_element(pl2,
l = .6, b = .1, r = 1, t = .6) + pt) / pl3
```
## 练习
```{r}
library(palmerpenguins)
library(ggthemes)
penguins
```
## 效果
```{r}
#| echo: false
#| warning: false
#| fig-width: 8
#| fig-height: 5
penguins |>
ggplot(aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point(aes(color = species, shape = species)) +
geom_smooth(method = "lm") +
labs(
title = "Body mass and flipper length",
subtitle = "Dimensions for Adelie, Chinstrap, and Gentoo Penguins",
x = "Flipper length (mm)",
y = "Body mass (g)",
color = "Species",
shape = "Species"
) +
scale_color_colorblind()
```
```{r}
#| include: false
#| fig-alt: |
#| A blank, gray plot area.
ggplot(data = penguins)
```
```{r}
#| include: false
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
)
```
```{r}
#| include: false
#| fig-alt: |
#| A scatterplot of body mass vs. flipper length of penguins. The plot
#| displays a positive, linear, and relatively strong relationship between
#| these two variables.
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point()
```
```{r}
#| include: false
#| warning: false
#| fig-alt: |
#| A scatterplot of body mass vs. flipper length of penguins. The plot
#| displays a positive, fairly linear, and relatively strong relationship
#| between these two variables. Species (Adelie, Chinstrap, and Gentoo)
#| are represented with different colors.
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g, color = species)
) +
geom_point()
```
```{r}
#| include: false
#| warning: false
#| fig-alt: |
#| A scatterplot of body mass vs. flipper length of penguins. Overlaid
#| on the scatterplot are three smooth curves displaying the
#| relationship between these variables for each species (Adelie,
#| Chinstrap, and Gentoo). Different penguin species are plotted in
#| different colors for the points and the smooth curves.
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g, color = species)
) +
geom_point() +
geom_smooth(method = "lm")
```
```{r}
#| include: false
#| warning: false
#| fig-alt: |
#| A scatterplot of body mass vs. flipper length of penguins. Overlaid
#| on the scatterplot is a single line of best fit displaying the
#| relationship between these variables for each species (Adelie,
#| Chinstrap, and Gentoo). Different penguin species are plotted in
#| different colors for the points only.
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point(mapping = aes(color = species)) +
geom_smooth(method = "lm")
```
```{r}
#| include: false
#| warning: false
#| fig-alt: |
#| A scatterplot of body mass vs. flipper length of penguins. Overlaid
#| on the scatterplot is a single line of best fit displaying the
#| relationship between these variables for each species (Adelie,
#| Chinstrap, and Gentoo). Different penguin species are plotted in
#| different colors and shapes for the points only.
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point(mapping = aes(color = species, shape = species)) +
geom_smooth(method = "lm")
```
## 练习
:::: {.panel-tabset}
### Code
```{r}
p <- ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point(aes(color = species, shape = species)) +
geom_smooth(method = "lm") +
labs(
title = "Body mass and flipper length",
subtitle = "Dimensions for Adelie, Chinstrap, and Gentoo Penguins",
x = "Flipper length (mm)", y = "Body mass (g)",
color = "Species", shape = "Species"
) +
scale_color_colorblind()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 练习
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
#| fig-alt: |
#| A scatterplot of body mass vs. flipper length of penguins, colored
#| by bill depth. A smooth curve of the relationship between body mass
#| and flipper length is overlaid. The relationship is positive,
#| fairly linear, and moderately strong.
p <- ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point(aes(color = bill_depth_mm)) +
geom_smooth()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 练习
:::: {.panel-tabset}
### Code
```{r}
p <- ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g, color = island)
) +
geom_point() +
geom_smooth(se = FALSE)
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 分层展示
:::: {.panel-tabset}
### Code
```{r}
p <- ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point() +
geom_smooth()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 柱状图
:::: {.panel-tabset}
### Code
```{r}
#| fig-alt: |
#| A bar chart of frequencies of species of penguins: Adelie
#| (approximately 150), Chinstrap (approximately 90), Gentoo
#| (approximately 125).
p <- ggplot(penguins, aes(x = species)) +
geom_bar()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 柱状图
:::: {.panel-tabset}
### Code
```{r}
#| fig-alt: |
#| A bar chart of frequencies of species of penguins, where the bars are
#| ordered in decreasing order of their heights (frequencies): Adelie
#| (approximately 150), Gentoo (approximately 125), Chinstrap
#| (approximately 90).
p <- ggplot(penguins, aes(x = fct_infreq(species))) +
geom_bar()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 直方图
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
#| fig-alt: |
#| A histogram of body masses of penguins. The distribution is unimodal
#| and right skewed, ranging between approximately 2500 to 6500 grams.
p <- ggplot(penguins, aes(x = body_mass_g)) +
geom_histogram(binwidth = 200)
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 直方图
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
#| layout-ncol: 2
#| fig-width: 3
#| fig-alt: |
#| Two histograms of body masses of penguins, one with binwidth of 20
#| (left) and one with binwidth of 2000 (right). The histogram with binwidth
#| of 20 shows lots of ups and downs in the heights of the bins, creating a
#| jagged outline. The histogram with binwidth of 2000 shows only three bins.
p1 <- ggplot(penguins, aes(x = body_mass_g)) +
geom_histogram(binwidth = 20)
p2 <- ggplot(penguins, aes(x = body_mass_g)) +
geom_histogram(binwidth = 2000)
p <- p1 + p2
```
### Graphic
```{r}
#| echo: false
#| fig-width: 10
#| fig-height: 5
p
```
::::
## 密度图
:::: {.panel-tabset}
### Code
```{r}
#| fig-alt: |
#| A density plot of body masses of penguins. The distribution is unimodal
#| and right skewed, ranging between approximately 2500 to 6500 grams.
p <- ggplot(penguins, aes(x = body_mass_g)) +
geom_density()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 箱图
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
#| fig-alt: |
#| Side-by-side box plots of distributions of body masses of Adelie,
#| Chinstrap, and Gentoo penguins. The distribution of Adelie and
#| Chinstrap penguins' body masses appear to be symmetric with
#| medians around 3750 grams. The median body mass of Gentoo penguins
#| is much higher, around 5000 grams, and the distribution of the
#| body masses of these penguins appears to be somewhat right skewed.
p <- ggplot(penguins,
aes(x = species, y = body_mass_g)) +
geom_boxplot()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 分组
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
#| fig-alt: |
#| A density plot of body masses of penguins by species of penguins. Each
#| species (Adelie, Chinstrap, and Gentoo) is represented with different
#| colored outlines for the density curves.
p <- ggplot(penguins,
aes(x = body_mass_g, color = species)) +
geom_density(linewidth = 0.75)
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 分组
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
#| fig-alt: |
#| A density plot of body masses of penguins by species of penguins. Each
#| species (Adelie, Chinstrap, and Gentoo) is represented in different
#| colored outlines for the density curves. The density curves are also
#| filled with the same colors, with some transparency added.
p <- ggplot(penguins,
aes(x = body_mass_g, color = species, fill = species)) +
geom_density(alpha = 0.5)
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 分组
:::: {.panel-tabset}
### Code
```{r}
#| fig-alt: |
#| Bar plots of penguin species by island (Biscoe, Dream, and Torgersen)
p <- ggplot(penguins,
aes(x = island, fill = species)) +
geom_bar()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 分组
:::: {.panel-tabset}
### Code
```{r}
#| fig-alt: |
#| Bar plots of penguin species by island (Biscoe, Dream, and Torgersen)
#| the bars are scaled to the same height, making it a relative frequencies
#| plot
p <- ggplot(penguins,
aes(x = island, fill = species)) +
geom_bar(position = "fill")
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 分组
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
#| fig-alt: |
#| A scatterplot of body mass vs. flipper length of penguins. The plot
#| displays a positive, linear, relatively strong relationship between
#| these two variables.
p <- ggplot(penguins,
aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 分组
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
#| fig-alt: |
#| A scatterplot of body mass vs. flipper length of penguins. The plot
#| displays a positive, linear, relatively strong relationship between
#| these two variables. The points are colored based on the species of the
#| penguins and the shapes of the points represent islands (round points are
#| Biscoe island, triangles are Dream island, and squared are Torgersen
#| island). The plot is very busy and it's difficult to distinguish the shapes
#| of the points.
p <- ggplot(penguins,
aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point(aes(color = species, shape = island))
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 分面
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
#| fig-width: 8
#| fig-asp: 0.33
#| fig-alt: |
#| A scatterplot of body mass vs. flipper length of penguins. The shapes and
#| colors of points represent species. Penguins from each island are on a
#| separate facet. Within each facet, the relationship between body mass and
#| flipper length is positive, linear, relatively strong.
p <- ggplot(penguins,
aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point(aes(color = species, shape = species)) +
facet_wrap(~island)
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 分面
:::: {.panel-tabset}
### Code
```{r}
#| warning: false
p <- ggplot(
data = penguins,
mapping = aes(
x = bill_length_mm, y = bill_depth_mm,
color = species, shape = species
)
) +
geom_point() +
labs(color = "Species")
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 练习
:::: {.panel-tabset}
### Code
```{r}
#| layout-ncol: 2
p1 <- ggplot(penguins, aes(x = island, fill = species)) +
geom_bar(position = "fill")
p2 <- ggplot(penguins, aes(x = species, fill = island)) +
geom_bar(position = "fill")
p <- p1 + p2
```
### Graphic
```{r}
#| echo: false
#| fig-width: 10
#| fig-height: 5
p
```
::::
## 练习
:::: {.panel-tabset}
### Code
```{r}
p <- ggplot(penguins,
aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 练习
:::: {.panel-tabset}
### Code
```{r}
p <- ggplot(mpg, aes(x = class)) +
geom_bar()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 练习
:::: {.panel-tabset}
### Code
```{r}
p <- ggplot(mpg, aes(x = cty, y = hwy)) +
geom_point()
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 练习
:::: {.panel-tabset}
### Code
```{r}
p <- ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy))
```
### Graphic
```{r}
#| echo: false
#| fig-width: 8
#| fig-height: 5
p
```
::::
## 欢迎讨论!{.center}
`r rmdify::slideend(wechat = FALSE, type = "public", tel = FALSE, thislink = "https://drwater.rcees.ac.cn/course/public/RWEP/@PUB/SD/")`