library(tidyverse)
library(here)
library(janitor)
# Wczytujemy dedykowany styl z projektu
source(here("R", "theme_course.R"))
theme_set(theme_course())16 Wykres Heatmap
Kolejnym potężnym narzędziem w arsenale wizualizacji danych jest Heatmap (mapa ciepła). Pozwala ona na pokazanie zagęszczenia zjawiska w czasie (lub w innej dwuwymiarowej przestrzeni) za pomocą skali kolorów.
Jako świetny przykład przeanalizujemy zbiór tf_birthdays.csv, który zawiera łączną liczbę osób urodzonych każdego dnia roku w Belgii.
Zbudujemy wykres inspirowany popularnymi wizualizacjami prasowymi (np. z New York Times czy narzędzia Datawrapper), na którym oś X to miesiące, oś Y to dni miesiąca, a kolor określa natężenie liczby narodzin.
16.1 Przetwarzanie danych
Dane wymagają lekkiego przekształcenia. Przypiszemy miesiącom polskie nazwy i ustawimy dni miesiąca w odpowiedniej kolejności (od 1 na górze do 31 na dole), aby siatka czytała się jak klasyczny kalendarz.
df_raw <- read_csv(here("datasets", "tf_birthdays.csv")) |>
clean_names()
# Polskie nazwy miesięcy
miesiace <- c("Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru")
df_heat <- df_raw |>
select(day, month, belgium) |>
mutate(
# Zamieniamy liczby na nazwy miesięcy (factor wymusza poprawną kolejność chronologiczną, a nie alfabetyczną)
month_name = factor(miesiace[month], levels = miesiace),
# Odwracamy dni, żeby 1. dzień miesiąca był na samej górze osi Y
day_fct = factor(day, levels = 31:1),
# Jeżeli zbiór ma zapisane "0" dla nieistniejących dni (np. 30 lutego), zamieniamy to na NA (brak danych),
# aby uniknąć błędnego kolorowania tych kratek
belgium = if_else(belgium == 0, NA_real_, belgium)
)16.2 Wykres
Do narysowania kratek (płytek) użyjemy geometrii geom_tile(). Do wypełnienia kolorami skorzystamy z domyślnej skali Viridis, która jest czytelna dla osób z zaburzeniami widzenia barw i dobrze komponuje się z naszym theme_course().
ggplot(df_heat, aes(x = month_name, y = day_fct, fill = belgium)) +
# geom_tile z białymi ramkami, co stworzy efekt siatki kalendarza
geom_tile(color = "white", linewidth = 0.8) +
# Skala Viridis (opcja magma lub domyślna viridis).
# direction = -1 sprawia, że ciemniejsze kolory to wyższe wartości.
scale_fill_viridis_c(
option = "viridis",
direction = -1,
na.value = "transparent", # Puste komórki (nieistniejące dni) będą przezroczyste
labels = scales::comma_format(big.mark = " "),
limits = c(29000, 34000), # Zawężamy skalę, by wykluczyć obserwacje odstające (jak 1 lipca, 1 stycznia czy 29 lutego)
oob = scales::squish # Funkcja squish sprawia, że wartości poza limitem otrzymują skrajne barwy skali
) +
# Przenosimy oś X (nazwy miesięcy) na górę wykresu dla wygody czytania
scale_x_discrete(position = "top") +
labs(
title = "Które daty urodzenia są najbardziej popularne?",
subtitle = "Całkowita liczba osób urodzonych danego dnia (dane dla Belgii)",
x = NULL,
y = "Dzień miesiąca",
fill = "Liczba urodzeń",
caption = "Źródło: dataset tf_birthdays.csv"
) +
# Dalsze modyfikacje estetyczne
theme_minimal() +
theme(
# Ukrywamy główne linie siatki, ponieważ same płytki geom_tile tworzą siatkę
panel.grid = element_blank(),
# Wyróżniamy tekst osi
axis.text.y = element_text(size = 9, color = "#555555"),
axis.text.x = element_text(size = 11, face = "bold", color = "#333333"),
# Przenosimy legendę na prawo, żeby łatwiej czytać wartości i wydłużamy jej pasek
legend.position = "right",
legend.title = element_text(face = "bold", size = 10),
legend.text = element_text(size = 9),
legend.key.height = unit(1.5, "cm"),
# Nagłówki
plot.title = element_text(face = "bold", size = 18),
plot.subtitle = element_text(color = "#555555", size = 12, margin = margin(b = 15)),
plot.caption = element_text(color = "#999999", margin = margin(t = 15))
)