---
title: "Wprowadzenie do ggplot2"
subtitle: "Statystyczne i graficzne podstawy geowizualizacji"
author: Anna Dmowska, dmowska@amu.edu.pl
format:
  html: 
    theme: cosmo
    toc: true
    toc-location: left
    toc-title: "Spis treści"
    number-sections: true
editor: visual
---

## Pakiet ggplot2

Do tworzenia wykresów w R wykorzystuje się pakiet **ggplot2**, który jest oparty na koncepcji ***Grammar of Graphics*** (Gramatyka Grafiki).

Aby stworzyć podstawowy wykres należy określić 3 kluczowe komponenty:

-   dane (*data*),
-   aspekty estetyczne (ang. *aestethic*)
-   przynajmniej jedną warstwę określającą elementy geometryczne czy transformacje statystyczne (*geom\_()*).

### Aspekty estetyczne (ang. *Aesthetic Mapping*)

Aspekty estetyczne (estetyki) definiują każdy aspekt danego elementu graficznego. W pakiecie ggplot2 *aesthetic* oznacza "coś co widzimy". Np:

-   pozycja na osi x oraz y
-   kolor
-   wypełnienie (wewnętrzny kolor obiektu)
-   kształt (dla obiektów punktowych)
-   typ linii
-   wielkość

### Elementy geometryczne - (ang. Geometic Objects (geom))

Elementy geometryczne reprezentują symbol wyświetlany na wykresie, np:

-   punkty (geom_point)
-   linie (geom_line)
-   określony typ wykresu: geom_boxplot, geom_histogram

Każdy wykres musi mieć określony przynajmniej jeden element geometryczny. Nie ma jednak górnej granicy. Używając znak + można dodawać dowolną ilość elementów

Dostępne typy obiektów: help.search(“geom\_”, package = “ggplot2”)

## Przykład 1: Pierwszy wykres

Zbiór danych przedstawia miesięczną średnią temperaturę powietrza dla miasta A i B i składa się z 3 kolumn: temperatura, miasto oraz mce.

```{r}
dane = data.frame(temperatura = c(-0.6, 0.4, 3.8, 9.4, 14.4, 17.8, 19.8, 19.5, 15.0, 9.9, 5.2, 1.4, -3.3, -2.2, 1.8, 8.3, 13.8, 17.2, 19.5, 18.7, 13.8, 8.1, 3.6, -0.6),
                miasto = rep(c("A", "B"), each = 12),
                mce = c(1:12, 1:12))
head(dane)
```

W pakiecie **ggplot2** do konstrukcji wykresu wykorzystuje się funkcję `ggplot()` w ramach, której definiuje się argument `data` oraz używa się funkcji `aes()`.

-   `data = dane` - określa nazwę ramki danych zawierającej 3 zmienne: temperatura, miasto, mce
-   `aes(x = mce, y = temperatura, color = miasto)` - określa, że zmienna `mce` ma być przedstawiona na osi x, zmienna `temperatura` na osi y, dodatkowo wyświetlane elementy mają mieć przypisany kolor zgodnie z kategoriami zmiennej `miasto`.

```{r}
library(ggplot2)
ggplot(data = dane, aes(x = mce, y = temperatura, color = miasto)) 
```

Zwróć uwagę, że wykres ma podpisane osie, ale nie wyświetlają się żadne elementy. W kolejnym kroku musimy określić za pomocą jakich elementów geometrycznych ma być pokazana temperatura dla poszczególnych miesięcy.

-   `geom_line()` oznacza, że dane mają być przedstawione jako wykres liniowy.

Poszczególne komponenty łączu się znakiem +.

```{r}
library(ggplot2)

ggplot(data = dane, aes(x = mce, y = temperatura, color = miasto)) +
  geom_line()
```

Powyższy wykres można rozbudować o dodatkowe elementy.

-   `geom_line()` - pozwala na podanie szeregu parametrów określających sposób wyświetlania linii, np. jej szerokość (*linewidth = 1.2*),
-   `geom_point()` - jest wykorzystywany do wyświetlenia punktów o współrzędnych określonych przez zmienną mce oraz temperatura, dla których można zdefiniować np. ich wielkość (*size*) oraz kształt (*shape*),

```{r}
ggplot(data = dane, aes(x = mce, y = temperatura, color = miasto)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 4, shape = 15) 
```

Aby sformatować osie musimy użyć `scale_x_continuous()`, który służy do określenia wartości wyznaczanych na osi x, np. zakres wartości, krok. W naszym przykładzie oś x przedstawia miesiące, chcemy zatem wyświetlić liczby od 1 do 12 z krokiem co 1. Parametr `breaks` określa krok z jakim mają być wyświetlane wartości, a `labels` oznacza wyświetlane etykiety.

```{r}
ggplot(data = dane, aes(x = mce, y = temperatura, color = miasto)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 4, shape = 15) +
  scale_x_continuous(breaks = seq(1, 12, 1), labels = c(seq(1,12, 1))) 
```

Aby zmienić kolor wyświetlanych linii użyjemy `scale_color_manual()`, który służy do określenia sposobu przypisania kolorów na wykresie. Kolor jest przypisywany na podstawie zmiennej *miasto*, która ma kategorie A i B. Kategorii A przypiszemy kolor ciemnoniebieski, a kategorii B - jasnoniebieski. Argument *name* określa nazwę, która ma się wyświetlić w legendzie.

```{r}
ggplot(data = dane, aes(x = mce, y = temperatura, color = miasto)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 4, shape = 15) +
  scale_x_continuous(breaks = seq(1, 12, 1), labels = c(seq(1,12, 1))) + 
  scale_color_manual(name = "Miasto", values = c("A" = "darkblue", "B" = "lightblue")) 
```

Etykiety osi oraz tytuł wykresu można określić za pomocą funkcji `labs()`.

```{r}
ggplot(data = dane, aes(x = mce, y = temperatura, color = miasto)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 4, shape = 15) +
  scale_x_continuous(breaks = seq(1, 12, 1), labels = c(seq(1,12, 1))) + 
  scale_color_manual(name = "Miasto", values = c("A" = "darkblue", "B" = "lightblue")) + 
  labs(title = "Średnia miesięcza temperatura w mieście A i B",
       x = "Miesiąc",
       y = "Temperatura (°C)")
```

Wizualny styl wykresu (kolor tła, wielkość czcionki itp.) określa `theme_minimal()`. Argument *base_size = 14* oznacza, że tytuł i etykiety osi mają mieć wielkość czcionki 14.

```{r}
ggplot(data = dane, aes(x = mce, y = temperatura, color = miasto)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 4, shape = 15) +
  scale_x_continuous(breaks = seq(1, 12, 1), labels = c(seq(1,12, 1))) + 
  scale_color_manual(name = "Miasto", values = c("A" = "darkblue", "B" = "lightblue")) + 
  labs(title = "Średnia miesięcza temperatura w mieście A i B",
       x = "Miesiąc",
       y = "Temperatura (°C)") +
  theme_minimal(base_size = 14) 
```

Dodatkowe elementy jak pozycje legendy można zmienić używając `theme()`.

```{r}
ggplot(data = dane, aes(x = mce, y = temperatura, color = miasto)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 4, shape = 15) +
  scale_x_continuous(breaks = seq(1, 12, 1), labels = c(seq(1,12, 1))) + 
  scale_color_manual(name = "Miasto", values = c("A" = "darkblue", "B" = "lightblue")) + 
  labs(title = "Średnia miesięcza temperatura w mieście A i B",
       x = "Miesiąc",
       y = "Temperatura (°C)") +
  theme_minimal(base_size = 14) +  
  theme(legend.position = "bottom") 
```

Kompletny kod wykresu wygląda następująco:

```{r}
ggplot(data = dane, aes(x = mce, y = temperatura, color = miasto)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 4, shape = 15) +
  scale_x_continuous(breaks = seq(1, 12, 1), labels = c(seq(1,12, 1))) + 
  scale_color_manual(name = "Miasto", values = c("A" = "darkblue", "B" = "lightblue")) + 
  labs(title = "Średnia miesięcza temperatura w mieście A i B",
       x = "Miesiąc",
       y = "Temperatura (°C)") +
  theme_minimal(base_size = 14) +  
  theme(legend.position = "bottom") 
```

## Przykład 2. PKB na osobę w Polsce w latach 1990-2007.

```{r}
#| message: false
library(tidyverse)
```

-   Wczytanie danych

```{r}
dane = read.csv("dane/gapminder_regions.csv")
```

-   Przygotowanie danych

```{r}
dane = dane |>  
  na.omit() |>  
  mutate(across(where(is.character), as.factor)) |>  
  mutate(income_grp = factor(income_grp, levels = c(1,2,3), labels = c("niski", "średni", "wysoki")))
```

-   Selekcja danych dla Polski od roku 1990

```{r}
pl = dane |>  
  filter(kraj == "Polska", rok >= 1990)
```

-   Wykres słupkowy przedstawiający wartość PKB w kolejnych latach

Do wykonania wykresu słupkowego pokazującego wartość zmiennej ilościowej w określonych kategoriach wykorzystuje się `geom_col()`. `labs()` służy do dodania tytułu wykresu oraz etykiet osi. Styl wykresu określa `theme_bw()`.

```{r}
ggplot(data = pl, aes(x = rok, y = pkb)) +
  geom_col() +
  labs(x = "Rok", y = NULL, title = "PKB na osobę (USD, 2007)") + 
  theme_bw(base_size = 14)
```

Należy zwrócić uwagę na nieprawidłowy sposób wyświetlania roku. Zmienna *rok* jest zmienną numeryczną i nie jest traktowana jako kategorie. Aby wyświetlić PKB w podziale na lata, zmienną *rok* trzeba przekształcić na zmienną czynnikową. Można to zrobić wewnątrz funkji `aes()` przypisując *x = as.factor(rok)*.

```{r}
ggplot(data = pl, aes(x = as.factor(rok), y = pkb)) +
  geom_col() +
  labs(x = "Rok", y = NULL, title = "PKB na osobę (USD, 2007)") + 
   theme_bw(base_size = 14)
```

## Przykład 3. PKB na osobę w wybranych krajach w 2002 roku.

```{r}
sel = dane |>  
  filter(kraj %in% c("Polska", "Czechy", "Słowacja", "Niemcy", "Wielka Brytania","Francja", "Bośnia i Hercegowina") & rok == 2002)
```

-   Wykres słupkowy

```{r}
ggplot(data = sel, aes(x = kraj, y = pkb)) + 
  geom_col()
```

-   Słupki na wykresie można posortować używając funkcji `fct_reorder()`. `fct_reorder(kraj, -pkb)` oznacza, że nazwy krajów mają być posortowane wg wartości zmiennej pkb malejąco (-pkb).

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb)) +
  geom_col() 
```

-   Dodanie opisów osi

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb)) +
  geom_col() + 
  labs(x = "Kraj", y = "PKB na osobę") 
```

-   Formatowanie etykiet osi. Tekst przypisany do osi formatuje się za pomocą argumentów wewnątrz `theme()`:

    -   **axis.text = element_text(size = 16, color = "red", face = "bold.italic")** oznacza, że wartości na obu osiach mają być wyświetlone w kolorze czerwonym (*color = "red"*), czcionką o rozmiarze 16 (*size = 16*) oraz jako pogrubiona kursywa (*face = "bold.italic"*)

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb)) +
  geom_col() + 
  labs(x = "Kraj", y = "PKB na osobę") + 
  theme(axis.text = element_text(size = 16, color = "red", face = "bold.italic"))
```

-   Formatowanie etykiet osi. Tekst przypisany do osi formatuje się za pomocą argumentów wewnątrz `theme()`:

    -   **axis.text.x = element_text(angle = 90, hjust = 1, color = "green", face = "italic")** - axis.text.x służy do formatowania osi x, w przykładzie obrócono etykiety o 90 (angle = 90), zmieniono ich kolor na zielony oraz kursywę.

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb)) +
  geom_col() + 
  labs(x = "Kraj", y = "PKB na osobę") + 
  theme(axis.text = element_text(size = 16, color = "red", face = "bold.italic"),
        axis.text.x = element_text(angle = 90, hjust = 1, color = "green", face = "italic"))
```

-   Formatowanie etykiet osi. Tekst przypisany do osi formatuje się za pomocą argumentów wewnątrz `theme()`:

    -   **axis.title = element_text(size = 20, color = "lightblue", face = "bold", family = "Times New Roman")** - axis.title służy do formatowania podpisów osi.

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb)) +
  geom_col() + 
  labs(x = "Kraj", y = "PKB na osobę") + 
  theme(axis.text = element_text(size = 16, color = "red", face = "bold.italic"),
        axis.text.x = element_text(angle = 90, hjust = 1, color = "green", face = "italic"), 
        axis.title = element_text(size = 20, color = "lightblue", face = "bold", family = "Times New Roman"))
```

-   W poniższym przykładzie etykiety osi x zostały obrócone o 90 stopni.

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb)) +
  geom_col() + 
  labs(x = "Kraj", y = "PKB na osobę") + 
  theme_minimal(base_size = 16) + theme(axis.text.x = element_text(angle = 90, hjust = 1))
```

-   W poniższym przykładzie zastosowano `coord_flip()` do zamiany osi x i y. W tym przypadku nie ma potrzeby zmiany kierunku etykiet osi y.

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb)) +
  geom_col() + 
  coord_flip() + 
  labs(x = "Kraj", y = "PKB na osobę") + 
  theme_minimal(base_size = 16) 
```

-   W poniższym przykładzie słupki dodatkowo mają przypisany kolor na podstawie zmiennej region (argument *fill = region* wewnątrz `aes()`).

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb, fill = region)) +
  geom_col() + 
  coord_flip() + 
  labs(x = "Kraj", y = "PKB na osobę") + 
  theme_minimal(base_size = 16) 
```

-   Aby zmienić kolor przypisany poszczególnym kategoriom można użyć np. `scale_fill_brewer()` oraz podać nazwę palety. Zmienna region jest zmienną jakościową, zatem musimy wybrać jedną z palet jakościowych, np. *Dark2* z pakietu **RColorBrewer**.

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb, fill = region)) +
  geom_col() + 
  coord_flip() + 
  scale_fill_brewer(palette = "Dark2") + 
  labs(x = "Kraj", y = "PKB na osobę") + 
  theme_minimal(base_size = 16) 
```

-   Można także przypisać określone kolory do określonych kategorii wykorzystując `scale_fill_manual()`

```{r}
ggplot(data = sel, aes(x = fct_reorder(kraj, -pkb), y = pkb, fill = region)) +
  geom_col() + 
  coord_flip() + 
  scale_fill_manual(values = c("Europa Południowa" = "orange", 
                                "Europa Wschodnia" = "red",
                                "Europa Zachodnia" = "darkgreen",
                                "Europa Północna" = "blue")) + 
  labs(x = "Kraj", y = "PKB na osobę") + 
  theme_minimal(base_size = 16) 
```

## Przykład 4. Zmiany średniej wartości PKB w latach 1952-2007

Funkcja `stat_summary()` służy do obliczania i wyświetlania statystyk danych na wykresie, bez konieczności ich wcześniejszego obliczania.

-   argument ***fun*** pozwala na określenie jaki parametr ma byc obliczony, np. średnia arytmetyczna (*fun = "mean"*), mediana (*fun = "median"*), odchylenie standardowe (*fun = "sd"*)
-   argument ***geom*** pozwala na określenie w jaki sposób wyniki statystyczne mają być wizualizowane, np. jako: punkty ("point"), linie ("line"), słupki ("bar").

```{r}
ggplot(data = dane, aes(x = rok, y = le)) + 
  stat_summary(fun = "mean", geom = "line")
```

Argumenty *color = "orange"*, *linewidth = 2*, *linetype = "dotted"* są wykorzystywane do formatowania linii.

```{r}
ggplot(data = dane, aes(x = rok, y = le)) + 
  stat_summary(fun = "mean", 
               geom = "line", 
               color = "orange", linewidth = 3, linetype = "dashed") 
```

```{r}
ggplot(data = dane, aes(x = rok, y = le)) + 
  stat_summary(fun = "mean", 
               geom = "line", 
               color = "orange", linewidth = 3, linetype = "dashed") + 
  scale_x_continuous(breaks = seq(1952, 2007, 5), labels = seq(1952, 2007, 5)) + 
  labs(x = "Rok", y = "Średnia długość trwania życia") 
```

> Zmień kolor linii na zielony, typ: linia kropkowana (dotted), grubość: 5. Wyświetl etykiety dla lat od 1952 do 2007 z krokiem co 5 lat. Użyj jednego z motywów wyświetlania: theme_bw(), theme_minimal(), theme_classic(), theme_dark(). Zmień wielkokść czcionki dla etykiet na 16.

## Zapisywanie wykresów 

Utworzony wykres można zapisać wykorzystując `ggsave()`

```{r}
p = ggplot(data = dane, aes(x = rok, y = le)) + 
  stat_summary(fun = "mean", 
               geom = "line", 
               color = "orange", linewidth = 3, linetype = "dashed") + 
  scale_x_continuous(breaks = seq(1952, 2007, 5), labels = seq(1952, 2007, 5)) + 
  labs(x = "Rok", y = "Średnia długość trwania życia") 
```


```{r}
#| message: false
#| warning: false
ggsave(filename = "Wykres.pdf", plot = p)
ggsave(filename = "Wykres.png", plot = p, dpi = 300)
```

## Zadanie samodzielne

1.  Wykonaj wykres słupkowy pokazujący jak zmieniała się długość trwania życia (zmienna le) w 1952 roku między Polską, Wielką Brytanią i Niemacami. Dodaj do wykresu opisy osi. Posortuj słupki od najwyższej do najniższej wartości.

2.  Wykonaj wykres słupkowy pokazujący jak zmieniała się wartość PKB w dowolnym państwie w latach 1952, 1962, 1972, 1982, 1992, 2002.

3.  Wybierz dane dla roku 1957 dla Japoni, Austrii, Włoch, Kanady, Somalii, Nigerii, Egiptu, Maroko, Indii, Chin, Polski, Stanów Zjednoczonych, Meksyku, Brazylii, Argentyny, Wenezuelii. Wykonaj wykres słupkowy pokazujący długość trwania życia w tych państwach. Pokoloruj słupki na podstawie nazw kontynentów. Dodaj etykiety osi oraz tytuł wykresu.
