---
title: "Wprowadzenie do ggplot2"
output:
  pdf_document: default
  html_document: default
---

`ggplot2` jest jednym z najczęściej wykorzystywanych pakietów do tworzenia grafiki w R. Pozwala tworzyć w łatwy sposób dość skomplikowane wykresy, posiada również dość rozsądne ustawienia standardowe, dzieki którym możemy uzyskać estetycznie wyglądające ilustracje małym nakładem pracy.

Nie jest on dołączy do podstawowej dystrybucji R i należy zainstalować go za pomocą polecenia `install.packages`. 

```{r}
# install.packages('ggplot2') # instalacja ggplot2
library(ggplot2)
```

Praca z `ggplot2` różni się od pracy z grafiką w standardowym R. Podstawowe różnice to:

1. Preferowana jest praca z ramkami danych, raczej nie zajdziemy za daleko pracując na pojedynczych wektorach.
2. Przestaje obowiązywać metafora płótna. Rysując w standardowym R mogliśmy podchodzić do tego jak do nakładania kolejnych linii, punktów, segmentów itp. za pomocą funkcji niskiego poziomu. W przypadku `ggplot2` raczej definiujemy wykres, nie przejmujemy się najczęściej niskopoziomowymi szczegółami.
3. Opiera się na teoretycznej koncepcji *grammar of graphics* i stara się ją implementować. 
4. Wykresy tworzymy dodając (`+` - `ggplot2` przeciąża operator dodawania) do siebie obiekty reprezentujące "warstwy" albo "mapowania" w specyficznej "gramatyce grafiki" implementowanej przez `ggplot2`.
5. Inaczej zapisujemy grafikę - używamy funkcji `ggsave`.

**Co będziemy omawiać:**

1. Zarys możliwości pakietu.
2. Tworzenie wykresów za pomocą `qplot` oraz gramatyki grafiki (mapowanie).
3. Różne rodzaje wykresów dla jednej lub dwóch zmiennych nominalnych i liczbowych.
4. Kilkupanelowe wykresy.

**Co nie będzie omawiane, ale jest ważną czescią pakietu `ggplot2`:**

1. Funkcje niskiego poziomu do rysowania kształtów.
2. Osie, skale.
3. Podpisy, napisy, przypisy (elementy tekstowe).
4. Drobnoziarnistwa kontrola.

Innymi słowy - w `ggplot2` możemy zmieniać detale tworzonych przez nas wykresów, ale nie będziemy omawiać każdej służącej do tego funkcji i jej argumentu. Informacje można łatwo znaleźć w Internecie, dokumentacja rozmaitych funkcji bogata jest też w przykłady.

# `qplot` - funkcja do szybkiego tworzenia wykresów (*quickplot*)

`qplot` jest *wrapperem* (można myśleć: skrótem) na inne funkcje `ggplot2`, który pozwala nam bardzo szybko i bez potrzeby żmudnego definiowania mapowan tworzyć proste wykresy. Z założenia funkcja `qplot` nie ma generować bardzo złożonych wykresów, lecz estetycznie wyglądające bardzo podstawowe typy wykresów. Przypomnijmy sobie jak wyglądały dane ze zbioru `beaver1` - będziemy na nich pracować.

```{r}
head(beaver1)
```

W przypadku, gdy w funkcji `qplot` podamy tylko jedną zmienną (`x`), `ggplot2` wyprodukuje domyślnie histogram.
Zmienne przekazujemy **bez cudzysłowiów** i są nimi **nazwy kolumn** w naszej ramce danych. Podajemy również argument `data`, w którym przekazujemy zmienną, w której znajduje się ramka danych, której chcemy używać.

```{r}
qplot(x = temp, data = beaver1)
```

Gdy podamy dwie zmienne - `x` oraz `y` - domyślnym rodzajem wykresu będzie wykres punktowy (*scatterplot*).

```{r}
qplot(x = time, y = temp, data = beaver1[beaver1$day == 346,])
```

Przekazując kolumnę z wektorem typu `factor` jako argument `color` możemy ustalić inne kolory ze względu na wartość tej kolumny. W poniższym przypadku punkty dotyczące obserwacji w obu dniach oznaczone są innymi kolorami. Warto zauważyć, że `ggplot2` automatycznie stworzył legendę (czego nie robią funkcje wbudowane w R!).

```{r}
beaver1$dzien <- as.factor(beaver1$day)
qplot(x = time, y = temp, color = dzien, data = beaver1)
```

Za pomocą argumentu `geom` możemy zmienić typ wykresu. Listę wszystkich możliwości z łatwością znajdą Państwo w internecie. Pokażemy sobie jednak kilka z nich. Ustawiając argument `geom` na `"line"` możemy stworzyć wykres liniowy.

```{r}
qplot(x = time, y = temp, geom = 'line', data = beaver1[beaver1$day == 346,])
```

`"step"` stworzy wykres schodkowy.

```{r}
qplot(x = time, y = temp, geom = 'step', data = beaver1[beaver1$day == 346,])
```

Jeśli do funkcji `plot` przekażemy dwie zmienne, z których jedna będzie kategorialna (`factor`), to `ggplot2` stworzy jeden ze znanych Państwu typów wykresów - na przykład wykres budełkowy. Jak jednak widzimy w przypadku wykresu pudełkowego argument `color` nie zadziałał tak, jak byśmy chcieli - pokolorował tylko linie na wykresie.

```{r}
qplot(x=dzien, y = temp, color = dzien, geom = 'boxplot', data = beaver1)
```

Jeżeli chcielibyśmy pokolorować również wypełnienie, musielibyśmy użyć argumentu `fill`. 

```{r}
qplot(x=dzien, y = temp, fill = dzien, geom = 'violin', data = beaver1)
```

# Tworzenie wykresów w języku grafiki `ggplot2`

`qplot` przydaje się przede wszystkim wtedy, kiedy chcemy stworzyć wykres *szybko* lub *nie jest skomplikowany*. Nie pozwala jednak wykorzystać wszystkich możliwości, jakie ma ten pakiet. Spróbujmy więc stworzyć wykres za pomocą "gramatyki grafiki" jaki implementuje `ggplot2`. 

## Jedna zmienna (lub dwie zmienne i jedna dyskretna)

Spróbujmy na początku stworzyć obiekt reprezentujący nasz wykres. Robimy to za pomocą funkcji `ggplot`.

```{r}
ggplot(data = beaver1)
```

Otrzymaliśmy puste płótno. Dlaczego? Oczywiście nie ustaliliśmy co ma być na osi rzędnych, co na odciętych. Stwórzmy więc obiekt, w którym przekażemy nasze mapowanie. Odpowiada za to argument `mapping` (będziemy go dalej pomijać i przekazywać wartości pozycyjnie), w którym przekazujemy obiekt stworzomy za pomocą funkcji `aes`.

```{r}
ggplot(data = beaver1, mapping = aes(x = temp))
```

Mamy już wykres, mamy już mapowanie - nawet dostaliśmy odpowiednie oznaczenia na osi. Nie mamy jednak na nim żadnego kształtu! Spróbujmy dodać do naszego wykresu jakiś kształt. Robimy to za pomocą funkcji `geom_rodzaj_kształtu`, którą "dodajemy" do już istniejącego obiektu.

```{r}
ggplot(data = beaver1, aes(x = temp)) + 
  geom_histogram()
```

Stworzyliśmy histogram! Jak Państwo widzą wygląda chyba troszkę ładniej niż standardowy histogram w R. 

No dobrze, ale czy możemy dodać jakiś inny kształt? Spróbujmy dodać małe kreseczki reprezentujące poszczególne obserwacje za pomocą `geom_rug`.

```{r}
ggplot(data = beaver1, aes(x = temp)) + 
  geom_histogram() + 
  geom_rug()
```

Wygląda to całkiem nieźle!

Mogą się Państwo zastanawiać skąd `ggplot2` wie, co i gdzie powinien narysować wówczas, gdy "dodajemy" kolejne kształty? `ggplot2` uwzględnia dorysowując do wykresu kolejne kształte mapowanie (`aes`) odziedziczone z głównego wykresu (= obiektu stworzonego przez funckję `ggplot`). Dlatego właśnie możemy po prostu dodawać kolejne kształty.

Nie musimy godzić się na mapowanie "odziedziczone" z głównego wykresu. Dla każdego kształtu (*geoma*) możemy mapowanie  zmienić lub uzupełnić o dodatkowe elementy. W tym celu używamy funkcji `aes`. W poniższym przykładzie użyliśmy wbudowanego w `ggplot2` słowa kluczowego `..density..` za pomocą którego zmieniliśmy wartości na osi y.

```{r}
ggplot(data = beaver1, aes(x = temp)) + 
  geom_histogram(aes(y = ..density..)) + 
  geom_rug()
```

Chociaż kolejne geomy dziedziczą mapowanie po pierwszym obiekcie, to możemy je oczywiście nadpisać. W tym przypadku podobnie jak w poprzednich dodaliśmy do naszego histogramu kreseczki za pomocą `geom_rug`, tym razem jednak dodaliśmy dodatkowe mapowanie - zmienna `dzien` ma być mapowana na kolor kreseczek.

```{r}
ggplot(data = beaver1, aes(x = temp)) + 
  geom_histogram(aes(y = ..density..)) + 
  geom_rug(aes(color = dzien))
```

Bez trudu możemy dodać jądrowy estymator gęstości dodając po prostu kolejny *geom* - tym razem `geom_density`. Proszę zwrócić uwagę, że zmieniliśmy jeszcze mapowanie kreseczek w `geom_rug`. `time` jest zmienną ciągłą (w miarę), więc `ggplot2` automatycznie dobrał ciągłą skalę kolorów i stworzył odpowiednią legendę.

```{r}
ggplot(data = beaver1, aes(x = temp)) + 
  geom_histogram(aes(y = ..density..)) + 
  geom_rug(aes(color = time)) + 
  geom_density()
```

`ggplot2` udostępnia oczywiście również rodzaje geomów bardziej wymyślne niż zwykłe histogramy. Na poniższym wykresie mają Państwo inny geom - `geom_dotplot`, który zamiast prostokątów rysuje kropki.

```{r}
ggplot(data = beaver1, aes(x = temp)) + 
  geom_dotplot() + 
  geom_rug()
```

Zwróćmy teraz uwagę na to, że w naszym zbiorze danych mamy dane z okresów aktywności i braku aktywności. Chcielibyśmy je rozdzielić, żeby lepiej zobrazować różnicę między nimi. Użyjemy do tego funkcji `facet_grid`, która w sposób automatyczny dzieli nasz wykres na panele według zadanego czynnika.

```{r}
beaver1['aktywnosc'] <- as.factor(beaver1$'activ')
ggplot(data = beaver1, aes(x = temp, fill = aktywnosc)) + 
  geom_dotplot() + 
  geom_rug() +
  facet_grid(.~aktywnosc) # możemy wybrać dwie zmienne, składnia to `zmienna1 ~ zmienna2`
```

Możemy próbować uatrakcyjnić nasz wykres. Proszę zauważyć, że każdy *geom* ma tutaj inne mapowanie - wysokosc słupków kropek reprezentuje liczbe zliczeń w danym "koszyku" hisgoramu, kolor kropek - aktywność bobra, kreseczki - dokładna wartość każdej obserwacji. Z kolei kolor kreseczek reprezentuje dzień, w którym ich dokonywaliśmy. Każda z tych rzeczy była osobną "warstwą", którą definiowaliśmy w gramatyce grafiki `ggplot2`.

```{r}
ggplot(data = beaver1, aes(x = temp)) + 
  geom_dotplot(aes(fill = aktywnosc, color = aktywnosc), 
               binpositions="all", stackgroups = TRUE) + 
  geom_rug(aes(color=dzien, fill = dzien)) 
```

Jeżeli chodzi o inne *geomy* w stylu histogramów to mamy jeszcze `geom_freqpoly`.

```{r}
ggplot(data = beaver1, aes(x = temp, fill = dzien, color = dzien)) + 
  geom_freqpoly()
```

Oraz `geom_area` (ten jest szczególnie efektowny).

```{r}
ggplot(data = beaver1, aes(x = temp, fill = dzien, color = dzien)) + 
  geom_area(stat='bin')
```

Jeżeli chodzi o wykresy słupkowe, to podobnie jak w standardowym R sami musimy policzyć wartości mające odpowiadać wysokości słupków. Jeśli mają to być zliczenia postąpimy więc tak:

```{r}
ggplot(data = beaver1, aes(x = dzien, fill = aktywnosc)) + 
  geom_bar()
```

Domyślnym zachowaniem jest ustawianie słupków na sobie, ale możemy je zmienić tak, by ustawiane były obok siebie.

```{r}
ggplot(data = beaver1, aes(x = dzien, fill = aktywnosc)) + 
  geom_bar(position= 'dodge')
```

Czasami jednak nie chcemy reprezentować na wykresie słupkowym liczby zliczeń czegoś, ale np. średnią, odchylenie standardowe, medianę. Wówczas chyba najprościej jest stworzyć sobie nową ramkę danych, w której będą obliczone te wartości i przekazać jako argument `stat` funkcji `geom_bar` wartość `"identity"`.

```{r}
df <- data.frame(sd = tapply(beaver1$temp, beaver1$dzien, sd), dzien = levels(beaver1$dzien))
df
ggplot(data = df, aes(y = sd, x = dzien, fill = dzien)) + 
  geom_bar(stat = 'identity')
```

Biblioteka `ggplot2` daje możliwość łączenia ze sobą kilka rodzajów wykresów. Na poniższym rysunku połączyliśmy wykres punktowy (z *jitterm* dla większej przejrzystosci) z wykresem skrzypcowym. Dodaliśmy również podpisy pod osiami oraz tytuł wykresu, zmieniliśmy też domyślne kolory (żeby mniej się zlewały).

```{r}
ggplot(data = beaver1) + 
  geom_violin(aes(x = dzien, y = temp, fill = dzien), draw_quantiles = c(0.25, 0.5, 0.75)) +
  geom_jitter(aes(x = dzien, y = temp, color = aktywnosc)) + 
  scale_fill_brewer(palette='Set1') +
  ggtitle('Wykres skrzypcowy') +
  labs(x='Dzień pomiarów', y='Temperatura')
```

## Dwie zmienne ciągłe.

W przypadku sytuacji, w której mamy dwie zmienne ciągłe postępujemy dokładnie tak samo. Do ilustracji posłużymy się zbiorem `iris`, który dotyczy kwiatków.

```{r}
head(iris)
```

Znów, samo wywołanie funkcji `ggplot` nic nie daje.

```{r}
ggplot(data = iris)
```

Nawet ustawienie mapowania nic nie daje, chociaż ustala nam osie i siatkę.

```{r}
ggplot(data = iris) +
  aes(x = Petal.Length, y = Petal.Width)
```

Pierwszy *geom* jaki omowimy to `geom_point` odpowiadający znanemu już nam wykresowy punktowemu.

```{r}
ggplot(data = iris) + 
  geom_point(aes(x = Sepal.Width, y = Sepal.Length))
```

Kstzałt punktów jest jedną z możliwościa mapowania zmiennej dyskretnej.

```{r}
ggplot(data = iris) + 
  geom_point(aes(x = Sepal.Width, y = Sepal.Length, shape = Species))
```

Podobnie jak poprzednio możemy dodać dodatkowe mapowanie, które trzecią zmienną - gatunek - mapuje jako kolor. Dodatkowo zmieniliśmy wygląd całego wykresu dodając jeden z kilku wbudowanych motywów (`theme_minimal`)

```{r}
ggplot(data = iris) + 
  geom_point(aes(x = Sepal.Width, y = Sepal.Length, col = Species)) + 
  theme_minimal()
```

Możemy oczywiście umieścić nasze punkty na trzech osobnych panelach w znany nam już sposób.

```{r}
ggplot(data = iris) +  
  geom_point(aes(x = Sepal.Width, y = Sepal.Length, col = Species)) + 
  facet_grid(. ~ Species) + 
theme_bw()
```

Panele możemy umieścić w innej orientacji zmieniając kolejnośc zmiennych w funkcji `facet_grid`. Warto zwrócić uwagę, że podpisy pod kategoriami są prawidłowo w pozycji poziomej. Pokazuję również inny motyw (`theme_dark`)

```{r}
ggplot(data = iris) +  
  geom_point(aes(x = Sepal.Width, y = Sepal.Length, col = Species)) + 
  facet_grid(Species~.) + 
  theme_dark()
```

Bardzo przydatne może być dla Państwa dodawanie linii regresji do wykresu punktowego. Pokazuje więc jak zrobić to za pomocą `stat_smooth`. Dopasowuje ona model liniowy do danych. Zacienione pole do przedział ufności (domyślnie 95%) dla linii regresji.

```{r}
ggplot(data = iris) +  
  facet_grid(.~Species) +
  stat_smooth(aes(x = Sepal.Width, y = Sepal.Length, col = Species), method = "lm", fullrange= TRUE)+
  geom_point(aes(x = Sepal.Width, y = Sepal.Length, col = Species))
```

Należy jednak pamiętać, że domyślnie dopasowywane jest nie model liniowy, ale ten: https://en.wikipedia.org/wiki/Local_regression
Linia jest więc pogięta, podobnie przedziały ufności.

```{r}
ggplot(data = iris, aes(x = Sepal.Width, y = Sepal.Length, col = Species)) +  
  geom_point() +
  geom_smooth() +
  facet_grid(.~Species)
```

Oczywiście nic nie stoi na przeszkodzie dodawać znane już nam geomy takie jak `geom_rug`.

```{r}
ggplot(data = iris, aes(x = Sepal.Width, y = Sepal.Length, col = Species)) +  
  geom_point() +
  geom_smooth() +
  geom_rug() +
  facet_grid(.~Species)
```

# Zakończenie - bardziej skomplikowany przykład.

W kolejnym przykładzie tworzymy bardziej skomplikowany wykres dotyczący rozmaitych parametrów diamentów. Dane znajdują się w zbiorze `diamonds`, który wbudowany jest w R.

```{r}
head(diamonds)
```

```{r}
ggplot(data = diamonds, aes(y=carat, x = cut, size = price, color = cut)) + 
  geom_jitter()
```

```{r}
ggplot(data = diamonds, aes(x=carat, y = price)) +  # podstawowe mapowanie
  geom_point(aes(color = color)) +  # mapowanie dla punktów: kolor diamentów -> kolor punktów
  facet_grid(clarity~cut) + # dzielimy na panele ze względu na przejrzystość i szlif
  stat_smooth(method = 'lm') + # dopasowujemy do danych linię regresji
  ggtitle('Diamenty przyjacielem studenta') +
  theme_minimal()
```

## Uwagi:

1. Proszę dobierać rodzaj wykresu do celu - inny będzie w specjalistycznym czasopiśmie, inny na prezentacji, inny na plakacie, inny w artykule prasowym, inny dla siebie do pracy.
2. Nie wszystkie mapowania są sobie równe - kwestie poznawcze.
3. Nie należy przesadzać, należy dobrze zaplanować co i dlaczego chcemy pokazać.
4. Ale nie warto bać się eksperymentowania. 

# Przydatne linki:

1. Plotly + `ggplot2` = wygryw: https://plot.ly/ggplot2/
2. Dokumentacja https://ggplot2.tidyverse.org/
3. Dodatki: https://exts.ggplot2.tidyverse.org/
5. Galeria grafik wg koncepcji Tufte'a - niektóre z wykorzystaniem `ggplot2`: http://motioninsocial.com/tufte/