---
title: "Podstawy grafiki w R"
author: "Bartosz Maćkiewicz"
subtitle: Statystyka I z R
output:
  pdf_document: default
  html_document: default
---

# Metafora płótna

W R dostępnych jest wiele bibliotek do tworzenia wykresów. My w tej części kursu zajmiemy się podstawową, wbudowaną w R biblioteką nazwaną `graphics`. O rysowaniu wykresów w R możemy myśleć jak o rysowaniu wykresów na płótnie. Płótno podzielone jest na kilka obszarów. Obszary rysowania wyglądają mniej więcej tak:

![Obszary rysowania](custombase-baseregions1fig.png)

Zwykle rysować będziemy na środkowym polu, a martwienie o pozostałe pola, takie zostawimy R.

Funkcje służące do rysowania w R możemy podzielić z grubsza na dwa typy. Pierwszy to funkcje wysokiego poziomu, drugi to funkcje niskiego poziomu.

## Funkcje wysokiego poziomu.

Funkcje wysokiego poziomu co do zasady rysują cały wykres, to znaczy zarówno same kształty na wykresie jak i legendę, podpisy, ramki,  osie, oznaczenia osi, tytuły, podtytuły itp. Przykładami funkcji wysokiego poziomu są funkcje `plot` (rysuje różne wykresy w zależności od przekazanych do funkcji danych) i `hist` (rysuje histogram).

## Funkcje niskiego poziomu.

Funkcje nieskiego poziomu rysują określone kształty, najczęściej na już narysowanych wykresach. Przydają się do ulepszania i modyfikowania wykresów już stworzonych za pomoca funkcji wysokiego poziomu, ale mogą też służyć do narysowania czegoś "od zera". Przykłady takich funkcji to `abline` (nakłada na wykres linię), `points` (nakłada na wykres punkty) lub `text` (nakłada na wykres tekst).

# Funkcja `plot`

Spróbujmy stworzyć najprostszy wykres punktowy (*scatterplot*, czasami po polsku również *wykres rozrzutu*). Użyjemy do tego znanego już z ćwiczeń domowych zbioru danych z bobrami i spróbujemy na wykresie zilustrować to,  jak zmieniała się temperatura bobra w czasie. Zobaczymy również różne rodzaje wykresów (argument `type` - za pomocą `?plot` można dowiedzieć się, jakie inne wartości może przyjmować) oraz jak określić tytuł wykresu (argument `main`).

W tym ćwiczeniu skorzystamy jedynie z podzbioru ramki danych `beaver1`. Chcemy użyć obserwacji pochodzącego z pierwszego dnia pomiarów.

```{r}
data(beavers)
beav <- beaver1[beaver1$day == 346, ] # wybieramy tylko dzień 346
# Zobaczymy jak wyglądają dane, które przekazujemy funkcji `plot`
head(beav) 
```

Funkcja `plot` w podstawowej formie przyjmuje dwa argumenty. Pierwszy to wektor ze współrzędnymi punktów na osi X, drugi to wektor ze współrzednymi punktów na osi Y. 

Poniżej znajdują się przykłady różnych typów wykresów.

```{r}
plot(beav$time, beav$temp, main = "Typ domyślny") 
plot(beav$time, beav$temp, type='b', main = "Typ 'b'")
plot(beav$time, beav$temp, type='l', main = "Typ 'l'")
plot(beav$time, beav$temp, type='o', main = "Typ 'o'")
plot(beav$time, beav$temp, type='o', axes = F, main = "Typ 'o' bez osi")
```

Spróbujmy nałożyć oba bobry na jeden wykres. Zrobimy to tworząc pierwszy z nich za pomocą funkcji wysokiego `plot`, a drugi za pomocą funkcji niskiego poziomu `points`. Funkcja `points` przyjmuje w zasadzie te same argumenty co `plot` ale rysuje wyłącznie punkty (a nie np. osie, podpisy itp.). W przypadku danych ze zbioru `beaver2` również skorzystamy z jednego dnia pomiarów.

```{r}
# wybieramy dane drugiego bobra z jednego dnia pomiarów
beav2 <- beaver2[beaver2$day == 307, ] 

plot(beav$time, beav$temp, type='o', 
     main='Temperatura bobrów', # główny tytuł wykresu
     sub='Bóbr 1 dzień 346 vs bóbr 2 dzień 307', # podtytuł wykresu
     col='Red', # kolor punktów
     ) 
points(beav2$time, beav2$temp, type='o', col='Blue') 
```

Niestety, niebieski bóbr wychodzi poza marginesy rysunku. Aby temu zapobiec, musimy ustawić skalę na osi Y tak, by obejmowała minimalne i maksymalne wartości obu bobór. W naszym przypadku R automatycznie dobiera wartości na Y tak, by mieścił się tylko pierwszy rysowany bóbr. Spróbujemy zmienić to zachowanie za pomocą argumenty `ylim`. 

```{r}
plot(beav$time, beav$temp, type='o', 
     main='Temperatura bobrów',
     sub='Bóbr 1 dzień 346 vs bóbr 2 dzień 307',
     col='Red', 
     ylim = c(min(c(beav$temp, beav2$temp)), # najmniejsza obserwacja dla obu bobrów
              max(c(beav$temp, beav2$temp))) # największa obserwacja dla obu bobrów
     )

points(beav2$time, beav2$temp, type='o', col='Blue')
```

Funkcja `points` to nie jedyna funkcja niskiego poziomu, której możemy użyć. Za pomocą funkcji niskiego poziomu `abline` dodajmy na rysunku średnią temperatury obu bobrów. Zmienimy także podpisy osi na bardziej adekwatne.

```{r}
plot(beav$time, beav$temp,
     type='o',
     main='Temperatura bobrów',
     col='Red', 
     ylim = c(min(c(beav$temp, beav2$temp)),
              max(c(beav$temp, beav2$temp))),
     # podpisy osi ustawia się za pomocą argumentów ylab i xlab
     ylab = 'Temperatura',
     xlab = 'Godzina') 
points(beav2$time, beav2$temp, type='o', col='Blue')

# abline przyjmuje różne argumenty 
# z argumentem `h` rysuje linię poziomą (horizontal) na określonej wysokości
abline(h = mean(beav$temp), col = 'Red')
abline(h = mean(beav2$temp), col = 'Blue')
```

## Graficzne funkcje niskiego poziomu

Poniżej znajduje się lista funkcji niskiego poziomu. Nie jest wyczerpująca, ale są to najbardziej przydatne funkcje. O każdej z tych funkcji można doczytać w dokumentacji. 

* `abline` - rysuje prostą
* `arrows` - dodaje strzałkę
* `axis` - dodaje dodatkowe osie
* `legend` - dodaje legendę
* `points` - rysuje punkty
* `lines` - rysuje linie
* `poly` - rysuje wielokąt
* `rect` - rysuje prostokąt
* `segments` - rysuje odcinki
* `text` - dodaje tekst
* `title` - dodaje tytuł

# Parametry graficzne

Możliwości personalizacji wykresów w R są niemal nieograniczone. Parametry graficzne rysowania można zmienić za pomocą funkcji `par`. Kilka przykładowych widzimy niżej. Uwaga! Należy pamiętać, że bardzo dużo rzeczy, które możemy ustawić w funkcji `par` możemy także przekazać jako argument naszej funkcji rysującej. 

```{r}
par(adj = 1, # 0 - tekst wyrównany do lewej, 0.5 - wycentrowany, 1 - tekst wyrównany do prawej 
    bg = 'skyblue', # kolor tła
    cex = 1.2, # powiększenie tekstu
    col = 'Green', # kolor wykresu i ramek 
    family = 'serif', # rodzina czcionki
    lty=3, # typ linii 
    lwd=1.3, # szerokość linii
    pch = 8) # symbol używany do oznaczania punktów

plot(beav$time, beav$temp, type='o', pch = 7) # symbol numer 8 to gwiazdki, ale my daliśmy 7 przy wywoływaniu funkcji
```

# `hist` - histogram

Histogram to typ wykresu, który bardzo często jest wykorzystywany do obrazowania rozkładu danych. Możemy go stworzyć za pomocą funkcji wysokiego poziomu `hist`.

```{r}
hist(beav$temp)
```

Spróbujmy wykonać trick polegający na naniesieniu dwóch histogramów na jeden wykres. Proszę uważnie prześledzić kod z komentarzami.

```{r}
# Tutaj stworzymy swoje "przezroczyste" kolory za pomocą funkcji adjustcolor.
# Bierzemy domyślne kolory R i ustawiamy kanał alfa (przezroczystosć) na 0.5
# Dzięki czemu stają się półprzezroczyste

t_red = adjustcolor('Red', alpha.f=0.5)
t_blue = adjustcolor('Blue', alpha.f=0.5)

# Tak jak przy wykresach punktowych musieliśmy ustawić skalę na osi Y,
# tak tutaj musimy zrobić to na osi X

hist(beav2$temp, 
     col = t_blue, 
     xlim = c(min(c(beav$temp, beav2$temp)),
              max(c(beav$temp, beav2$temp))))

# Przekazując argumentowi `add` wartość TRUE mówimy Rowi,
# żeby drugi histogram narysował na pierwszym.

hist(beav$temp,
     col = t_red,
     add = TRUE)
```

W kolejnym przykładzie robimy w zasadzie to samo, ale musimy sobie dodatkowo poradzić z jeszcze jednym problemem, polegajacym na doborze szerokości "koszyków" histogramu. W tym celu tworzymy zmienną `bins`, w której ustawiamy takie wartości koszyków, żeby oba wykresy mieściły się. Przekazujemy ją w argumencie `breaks`.

```{r}
bins <- seq(min(beav2$temp)-0.2, # początek pierwszego koszyka
            max(beav2$temp)+0.2, # koniec ostatniego koszyka
            by=0.2 # szerokość koszyka
            )
bins

hist(beav2$temp[beav2$activ == 1], # tylko okresy aktywne
     col = t_blue, 
     xlim = c(min(beav2$temp), max(beav2$temp)), 
     breaks = bins)

hist(beav2$temp[beav2$activ == 0], # tylko okresy nieaktywne
     col = t_red,
     breaks = bins,
     add = TRUE
     )
```

# `barplot` - wykres słupkowy

Wykres słupkowy to chyba najczęściej wykorzystywany w praktyce typ wykresu. Nie przekazuje za dużo informacji, ale często może się przydać. Często można go spotkać w mediach, na plakatach, na infografikach itp. Jest zdecydowanie lepszy, niż wykres kołowy, którego w zasadzie nigdy nie powinniśmy używać.


```{r}
df <- read.csv('student-por.csv', sep=";", header = TRUE)
table(df$Mjob) # tabela z której tworzymy wykres
# wykres, jako argument przyjmuje twór "macierzopodobny" - w tym wypadku tabelę
barplot(table(df$Mjob)) 
```

Wykres możemy upiększać ustawiając mu kolory oraz przerzucając go na drugi bok.

```{r}
df <- read.csv('student-por.csv', sep=";", header = TRUE)

# za pomocą prop.table możemy stworzyć wykres procentowy
prop.table(table(df$Mjob)) 

barplot(prop.table(table(df$Mjob)),
        col = c('Red', 'Blue', 'Green', 'Yellow', 'Grey'), # kolory
        horiz = TRUE) # orientacja pozioma
```

Jak działają wykresy procentowe z nakładającymi się kolumnami?

1. Musimy mieć tabelę procentową. Uzyskujemy taką za pomocą funkcji `prop.table`. Musimy pamiętać, by przekazać odpowiedni wymiar (`margin`)
2. Funkcja barplot kiedy przekażemy jej argument w postaci dwuwymiarowej tabeli, traktowac będzie kolumny jako kolumny na wykresie, a poszczególne wiersze jako kolejne segmenty.
3. Jeżeli ustawili Państwo dobrze wymiary, to wykresy powinny mieć tę samą wysokość.

```{r}
# za pomocą prop.table możemy stworzyć wykres procentowy
prop.table(table(df$studytime, df$Mjob),
           2 # proporcje sumują się do 1 w kolumnach
           ) 

barplot(prop.table(table(df$studytime, df$Mjob), 2),
        col = c('Red', 'Blue', 'Green', 'Yellow'), # kolory
        horiz = TRUE, # orientacja pozioma
        legend = TRUE) # legenda
```

Tutaj szybki sposób na naniesienie na wykres jakiegoś parametru naszych danych za pomocą funkcji `tapply` i `barplot`.

```{r}
barplot(tapply(df$G3, df$Mjob, mean))
```

# `boxplot` - wykres pudełkowy

Wykres pudełkowy został wymyślony przez Johna Tukeya jako prosta metoda wizualizacji danych. O ile wiem, po raz pierwszy został on opisany w książce *Exploratory Data Analysis*. Prawie każdy widział w swoim życiu wykres pudełkowy, niewiele osób potrafi jednak powiedzieć, co oznaczają jego poszczególne elementy i do czego się tak naprawdę odnoszą. Proszę nauczyć się odczytywać informacje z wykresów pudełkowych.

![Boxplot](Box-Plot-MTB_01.png)

Oraz przeczytać dowolny artykuł gdziekolwiek na ten temat. Moze być ten:

http://onlinestatbook.com/2/graphing_distributions/boxplots.html

W R możemy stworzyć wykres pudełkowy za pomocą funkcji `boxplot`. Poniższy kod rysuje dwupanelowy wykres. Na pierwszym panelu jest wykres pudełkowy ocen chłopców, na drugim - dziewcząt.

```{r}
par(mfrow = c(1,2))
boxplot(split(df, df$sex)[[2]]$G3, main = 'Chłopcy')
boxplot(split(df, df$sex)[[1]]$G3, main = 'Dziewczynki')
```

# `vioplot` - wykres skrzypcowy

Wykres skrzypcowy to bardziej nowoczesny odpowiednik wykresu pudełkowego. Można o nim myśleć jako o połączeniu histogramu (lub wykresu ilustrującego estymowaną z rozkładu empirycznego gęstość prawdopodobieństwa) oraz wykresu pudełkowego. Niektórym jego wygląd się kojarzy:

![Obrazek z XKCD, https://xkcd.com/1967/](violin_plots_xkcd.png)

Poniżej znajduje się wyjaśnienie, co oznaczają poszczególne elementy wykresu skrzypcowego:

![Wykres skrzypcowy](violin_plot.png)

Więcej o wykresie skrzypcowym można przeczytać na przykład na Wikipedii:  https://en.wikipedia.org/wiki/Violin_plot

```{r warning=FALSE, message=FALSE}
# musimy zainstalować pakiet `vioplot` tworzący wykres skrzypcowy
# install.packages("vioplot") 

library(vioplot)
par(mfrow = c(1,2))
vioplot(split(df, df$sex)[[2]]$G3)
vioplot(split(df, df$sex)[[1]]$G3)
```