library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 4.0.0 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.2.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(viridis)
## Loading required package: viridisLite
library(plotly)
##
## Attaching package: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following object is masked from 'package:graphics':
##
## layout
library(gganimate)
gapminder.coltypes <- cols(
country = col_factor(),
continent = col_factor(levels = c("Africa", "Americas", "Asia", "Europe", "Oceania")),
year = col_integer(),
lifeExp = col_double(),
pop = col_integer(),
gdpPercap = col_double()
)
gapminder <- read_csv("gapminder.csv", col_types = gapminder.coltypes)
gapminder |> head()
## # A tibble: 6 × 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Afghanistan Asia 1952 28.8 8425333 779.
## 2 Afghanistan Asia 1957 30.3 9240934 821.
## 3 Afghanistan Asia 1962 32.0 10267083 853.
## 4 Afghanistan Asia 1967 34.0 11537966 836.
## 5 Afghanistan Asia 1972 36.1 13079460 740.
## 6 Afghanistan Asia 1977 38.4 14880372 786.
These are the values used for year:
gapminder |>
distinct(year) |>
arrange(year) |>
pull(year)
## [1] 1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 2002 2007
These are the values used for continent:
gapminder |>
pull(continent) |>
levels()
## [1] "Africa" "Americas" "Asia" "Europe" "Oceania"
2d plot ignoring year:
This is a little weird, because each country appears several times.
gapminder |>
ggplot() +
geom_point(aes(x = gdpPercap, y = lifeExp, fill = continent, size = pop), shape = 21, alpha = 0.8, color = "black") + # shapes 21 - 25 support fill and color
scale_fill_manual(
"Continent",
values = viridis(7)[c(1, 3, 4, 6, 7)],
guide = guide_legend(override.aes = list(shape = 21, alpha = 1, size = 5, color = "black")) # ensures the legend key shows the fill color, only some shapes support this
) +
scale_size_continuous(
"Population",
breaks = c(5e7, 1e8, 5e8, 1e9, 2e9),
# labels = scales::comma,
labels = scales::label_number(scale = 1e-6, suffix = "M"),
range = c(0.1, 15)
) +
labs(x = "GDP per Capita", y = "Life Expectancy") +
theme(
legend.text.align = 1
)
2d plot for one year:
Better, but now we plot year 2007 only.
gapminder |>
filter(year == 2007) |>
ggplot() +
geom_point(aes(x = gdpPercap, y = lifeExp, fill = continent, size = pop), shape = 21, alpha = 0.8, color = "black") + # shapes 21 - 25 support fill and color
scale_fill_manual(
"Continent",
values = viridis(7)[c(1, 3, 4, 6, 7)],
guide = guide_legend(override.aes = list(shape = 21, alpha = 1, size = 5, color = "black")) # ensures the legend key shows the fill color, only some shapes support this
) +
scale_size_continuous(
"Population",
breaks = c(5e7, 1e8, 5e8, 1e9, 2e9),
# labels = scales::comma,
labels = scales::label_number(scale = 1e-6, suffix = "M"),
range = c(0.1, 15)
) +
labs(x = "GDP per Capita", y = "Life Expectancy") +
theme(
legend.text.align = 1
)
2d plot:
We can use shape to distinguish more than one year, but it gets a bit
crowded.
gapminder |>
filter(year %in% c(1997, 2002, 2007)) |>
ggplot() +
geom_point(aes(x = gdpPercap, y = lifeExp, fill = continent, shape = factor(year), size = pop), alpha = 0.8, color = "black") + # need factor(year) and not year
scale_shape_manual(
"Year",
values = c(21, 22, 23), # shapes 21–25 support both fill and border color
guide = guide_legend(override.aes = list(size = 5))
) +
scale_fill_manual(
"Continent",
values = viridis(7)[c(1, 3, 4, 6, 7)],
guide = guide_legend(override.aes = list(shape = 21, alpha = 1, size = 5, color = "black")) # ensures the legend key shows the fill color, only some shapes support this
) +
scale_size_continuous(
"Population",
breaks = c(5e7, 1e8, 5e8, 1e9, 2e9),
# labels = scales::comma,
labels = scales::label_number(scale = 1e-6, suffix = "M"),
range = c(0.1, 15)
) +
labs(x = "GDP per Capita", y = "Life Expectancy") +
theme(
legend.text.align = 1
)
Can you find India, China, and the USA in the plot above?
Maybe it is okay to look at fewer countries and plot all years using fill
gapminder |>
filter(country %in% c("China", "India", "United States", "Germany", "Austria")) |>
ggplot() +
geom_point(aes(x = gdpPercap, y = lifeExp, fill = year, shape = country, size = pop), alpha = 0.8, color = "black") + # use year and not factor(year) here
scale_shape_manual(
"Country",
values = c(21, 22, 23, 24, 25), # shapes 21 - 25 support fill and color
guide = guide_legend(override.aes = list(size = 5))
) +
scale_fill_viridis_c("Year") +
scale_size_continuous(
"Population",
breaks = c(5e7, 1e8, 5e8, 1e9, 2e9),
# labels = scales::comma,
labels = scales::label_number(scale = 1e-6, suffix = "M"),
range = c(0.1, 15)
) +
labs(x = "GDP per Capita", y = "Life Expectancy") +
theme(
legend.text.align = 1
)
In rare cases, it makes sense to build 3d plots.
plot_ly() |>
add_markers(data = gapminder, x = ~gdpPercap, y = ~year, z = ~lifeExp)
A better alternative is to use time directly and create an animation:
p <- ggplot(gapminder) +
geom_point(aes(x = gdpPercap, y = lifeExp, fill = continent, size = pop), shape = 21, alpha = 0.8, color = "black") + # shapes 21 - 25 support fill and color
scale_fill_manual(
"Continent",
values = viridis(7)[c(1, 3, 4, 6, 7)],
guide = guide_legend(override.aes = list(shape = 21, alpha = 1, size = 5, color = "black")) # ensures the legend key shows the fill color, only some shapes support this
) +
scale_size_continuous(
"Population",
breaks = c(5e7, 1e8, 5e8, 1e9, 2e9),
# labels = scales::comma,
labels = scales::label_number(scale = 1e-6, suffix = "M"),
range = c(0.1, 15)
) +
labs(x = "GDP per Capita", y = "Life Expectancy") +
theme(
legend.text.align = 1
) +
transition_time(year) +
ease_aes("linear")
n <- gapminder |>
distinct(year) |>
pull(year) |>
length()
animate(p, nframes = n, fps = 1) # we only plot our 12 time steps. Increasing means interpolating, one frame per second
Which country is on the top right?
gapminder |>
filter(gdpPercap > 70000)
## # A tibble: 5 × 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Kuwait Asia 1952 55.6 160000 108382.
## 2 Kuwait Asia 1957 58.0 212846 113523.
## 3 Kuwait Asia 1962 60.5 358266 95458.
## 4 Kuwait Asia 1967 64.6 575003 80895.
## 5 Kuwait Asia 1972 67.7 841934 109348.