Kod
library(dplyr)
library(ggplot2)
library(tidyr)
= readr::read_csv("data/gapminder_1950_2023.csv")
gm0 = select(gm0, Kraj, Rok, Ocz_dl_zycia, PKB_na_osobe)
df1 = filter(gm0, Rok == 2019) df0sel
Istnieje wiele klasyfikacji zmiennych wizualnych, w tym klasyfikacja Rotha (2017). W tej klasyfikacji zmienne wizualne są opisywane poprzez to czy są:
Dodatkowo, zmienne wizualne mogą być określone poprzez to do jakiego rodzaju zmiennych się odnoszą:
library(dplyr)
library(ggplot2)
library(tidyr)
= readr::read_csv("data/gapminder_1950_2023.csv")
gm0 = select(gm0, Kraj, Rok, Ocz_dl_zycia, PKB_na_osobe)
df1 = filter(gm0, Rok == 2019) df0sel
Zmienne wizualne w ggplot2 są zaimplementowane jako mapowania (aes). Nie zawierają one jednak wszystkich zmiennych wizualnych z klasyfikacji Rotha.
= data.frame(nazwa = c("x", "y", "color", "fill", "alpha", "size", "linewidth", "shape"),
zw_df typ = c("położenie", "położenie", "barwa", "barwa", "barwa", "znak", "znak", "znak"),
opis = c("położenie wzdłuż osi X", "położenie wzdłuż osi Y", "kolor linii lub obrysu", "kolor wypełnienia", "przezroczystość", "wielkość", "szerokość linii", "kształt"))
::kable(zw_df, caption = "Zmienne wizualne zaimplementowane w ggplot2") knitr
nazwa | typ | opis |
---|---|---|
x | położenie | położenie wzdłuż osi X |
y | położenie | położenie wzdłuż osi Y |
color | barwa | kolor linii lub obrysu |
fill | barwa | kolor wypełnienia |
alpha | barwa | przezroczystość |
size | znak | wielkość |
linewidth | znak | szerokość linii |
shape | znak | kształt |
To jakie zmienne wizualne można użyć w danej sytuacji zależy od rodzaju elementu graficznego, który chcemy zastosować. W przypadku powierzchni możemy użyć jedynie barwy. Dla linii możemy użyć barwy, grubości linii, czy też kształtu linii. Najbardziej uniwersalne są punkty, które mogą być zdefiniowane poprzez barwę, wielkość, czy kształt.
Komputerowa reprezentacja kolorów
= hcl.colors(7, "Set3")
p_cat = rev(hcl.colors(7, "Greens"))
p_seq = hcl.colors(7, "Temps")
p_div = hcl.colors(7, "Set2")
p_cat2 = rev(hcl.colors(7, "viridis"))
p_seq2 = hcl.colors(7, "Earth") p_div2
::show_col(p_cat, ncol = 7) scales
::show_col(p_seq, ncol = 7) scales
::show_col(p_div, ncol = 7) scales
Pakiet ggplot2 ma wbudowane różne skale kolorów, jednak są one dość ograniczone. Alternatywą jest pakiet colorspace, który oferuje większą ilość skal kolorów oraz prosty interfejs do ich wykorzystania.
Skale kolorystyczne z pakiety colorspace są wywoływane za pomocą schematu scale_<aesthetic>_<datatype>_<colorscale>()
, gdzie:
fill
, color
)discrete
, continuous
, binned
)qualitative
, sequential
, diverging
, divergingx
)Przykładowo, scale_color_continuous_sequential("Viridis")
ustawia skalę kolorów o nazwie Viridis dla estetyki koloru, dla zmiennej ciągłej, w sposób sekwencyjny.
library(colorspace)
Pakiety wizualizacyjne posiadają określone domyślne skale kolorów. Zazwyczaj są one wybierane na podstawie typu zmiennej, której dotyczy estetyka koloru. Inna skala będzie używana dla zmiennych ciągłych, a inna dla zmiennych dyskretnych.
Przykładowo, ggplot2 dla zmiennych ciągłych stosowuje sekwencyjną skalę kolorów od ciemnego do jasnego niebieskiego. W poniższym przypadku dodatkowo mamy do czynienia z dużymi wartościami prezentowanej zmiennej, w którym to przypadku wartości używają notacji naukowej.1
= ggplot(data = df0sel, aes(x = PKB_na_osobe, y = Ocz_dl_zycia,
gg1 color = Populacja)) +
geom_point(size = 1.5) +
labs(y = "Oczekiwana długość życia", x = "PKB na osobę")
gg1
Niżej można zobaczyć cztery warianty skali kolorów dla zmiennej ciągłej. Pierwsze dwa korzystają z sekwencyjną, ciągłą skalę kolorów Viridis, z tą różnicą, że wizualizacja po lepiej odwraca kolejność kolorów, a ta po prawej zmienia punkt początkowy i końcowy skali.
options(scipen = 999)
+ scale_color_continuous_sequential("Viridis", rev = FALSE)
gg1 + scale_color_continuous_sequential("Viridis", begin = 0.2, end = 0.8) gg1
Następne dwie wizualizacje również korzystają ze skali kolorów Viridis. Tym razem stosują one transformację logarytmiczną dla przedstawianej zmiennej ciągłej. Pozwala ona na lepsze zobrazowanie różnic między wartościami zmiennej. Wizualizacja po lewej stronie posiada sekwencyjną, ciągłą skalę kolorów, a ta po prawej korzysta z sekwencyjnej skali kolorów z podziałem na przedziały.
+ scale_color_continuous_sequential("Viridis", trans = "log10")
gg1 + scale_color_binned_sequential("Viridis", trans = "log10") gg1
::c4a_gui() cols4all
Możliwe jest również zdefiniowanie własnej skali kolorów.
= c("#FCDE9C", "#FAA476", "#F0746E", "#E34F6F", "#DC3977", "#B9257A",
moja_pal "#7C1D6F")
+ scale_color_gradientn(colors = moja_pal) # dla zmiennych ciągłych gg1
# scale_color_manual() -- dla zmiennych dyskretnych
Ślepota barw
library(colorblindcheck)
palette_check(moja_pal, plot = TRUE)
name n tolerance ncp ndcp min_dist mean_dist max_dist
1 normal 7 6.671338 21 21 6.671338 31.85827 71.68336
2 deuteranopia 7 6.671338 21 20 6.529856 26.89899 62.60736
3 protanopia 7 6.671338 21 21 8.092279 31.50976 71.15744
4 tritanopia 7 6.671338 21 20 3.751602 22.68229 52.68331
Domyślne wizualizacja zmiennych dyskretnych nadaje unikalny kolor dla każdej wartości zmiennej.
ggplot(data = df0sel, aes(x = PKB_na_osobe, y = Ocz_dl_zycia, color = Region)) +
geom_point(size = 1.5, alpha = 0.8)
Jest to zazwyczaj oczekiwane zachowanie. Czasem jednak celem wizualizacji może być podkreślenie relacji jednej z katogorii z resztą. W takiej sytuacji można stworzyć własną wersję skali kolorów, dla której część kolorów zostanie rozjaśniona i poddana zmniejszeniu nasycenia, a inne zostaną przyciemnione.
Poniższa rycina pokazuje ten proces, gdzie pierwszy wiersz przedstawia oryginalne kolory. W drugim wierszu pierwsze cztery kolory są rozjaśnione, a w trzecim wierszu dodatkowo mają zmniejszoną nasycenie. Ostatni wiersz przedstawia finalną skalę kolorów, gdzie trzy ostatnie kolory są przyciemnione.
= palette.colors(n = 8)[-1]
oi ::show_col(oi, ncol = 7)
scales1:4] = lighten(oi[1:4], .4)
oi[::show_col(oi, ncol = 7)
scales1:4] = desaturate(oi[1:4], .8)
oi[::show_col(oi, ncol = 7)
scales5:7] = darken(oi[5:7], .3)
oi[::show_col(oi, ncol = 7) scales
Zastosowanie tej skali kolorów można zobaczyć na kolejnej rycinie. Regionowi “Azja” został przypisany najciemniejszy kolor (siódmy), a pozostałe regiony otrzymały kolory z pierwszych trzech.
= oi[c(7, 3:1)]
sel_oi names(sel_oi) = c("Azja", "Europa", "Ameryka", "Afryka")
ggplot(data = df0sel, aes(x = PKB_na_osobe, y = Ocz_dl_zycia, color = Region)) +
geom_point(size = 1.5, alpha = 0.8) +
scale_color_manual(values = sel_oi)
library(colorblindcheck)
= hcl.colors(n = 7, palette = "Temps")
pal palette_check(pal, plot = TRUE)
name n tolerance ncp ndcp min_dist mean_dist max_dist
1 normal 7 15.22036 21 21 15.220363 36.65304 66.55783
2 deuteranopia 7 15.22036 21 12 5.294656 19.22404 41.68858
3 protanopia 7 15.22036 21 12 3.192646 20.36599 42.73267
4 tritanopia 7 15.22036 21 17 8.576467 35.96531 64.52385
= filter(gm0, Region == "Azja") df0az
library(forcats)
= ggplot(df0az, aes(Rok, fct_reorder(as.factor(Kraj), Ocz_dl_zycia,
ggcol3 n = 1, .desc = FALSE, .na_rm = TRUE),
tail, fill = Ocz_dl_zycia)) +
geom_tile() +
labs(y = NULL, x = NULL, fill = NULL, title = "Oczekiwana długość życia") +
scale_fill_continuous_divergingx(palette = "Temps", mid = 60, rev = TRUE) +
theme(axis.text = element_text(size = 20))
# remotes::install_github("clauswilke/colorblindr")
library(colorblindr)
= ggcol3 +
ggcol3c scale_fill_continuous_divergingx(palette = "Earth", mid = 60) +
theme(axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank()) +
labs(title = NULL)
cvd_grid(ggcol3c)
::specplot(pal) colorspace
= c("solid", "dashed", "dotted", "dotdash", "longdash", "twodash")
lty = data.frame(
linetypes y = seq_along(lty),
lty = lty
) ggplot(linetypes, aes(0, y)) +
geom_segment(aes(xend = 5, yend = y, linetype = lty)) +
scale_linetype_identity() +
geom_text(aes(label = lty), hjust = 0, nudge_y = 0.2) +
scale_x_continuous(NULL, breaks = NULL) +
scale_y_reverse(NULL, breaks = NULL)
= filter(df1, Kraj %in% c("Polska", "Niemcy", "Francja", "Włochy", "Hiszpania"))
df1sel ggplot(df1sel, aes(Rok, PKB_na_osobe, linetype = Kraj)) +
geom_line() +
scale_linetype_manual(values = c("solid", "dashed", "dotted", "dotdash", "longdash"))
= data.frame(
shapes shape = c(0:24),
x = 0:24 %/% 5,
y = -(0:24 %% 5)
)ggplot(shapes, aes(x, y)) +
geom_point(aes(shape = shape), size = 5, fill = "red") +
geom_text(aes(label = shape), hjust = 0, nudge_x = 0.15) +
scale_shape_identity() +
expand_limits(x = 4.1) +
theme_void()
ggplot(data = df0sel, aes(x = PKB_na_osobe, y = Ocz_dl_zycia, color = Region, shape = Region)) +
geom_point(size = 1.5, alpha = 0.8) +
scale_shape_manual(values = 21:24)
Przykładowo, 1e+9 oznacza 1 miliard, a 1e-3 oznacza 0,001.↩︎