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
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 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 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).
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.
data(beavers)
beav <- beaver1[beaver1$day == 346, ] # wybieramy tylko dzień 346
# Zobaczymy jak wyglądają dane, które przekazujemy funkcji `plot`
head(beav)
## day time temp activ
## 1 346 840 36.33 0
## 2 346 850 36.34 0
## 3 346 900 36.35 0
## 4 346 910 36.42 0
## 5 346 920 36.55 0
## 6 346 930 36.69 0
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.
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.
# 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
.
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.
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')
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 osielegend
- dodaje legendępoints
- rysuje punktylines
- rysuje liniepoly
- rysuje wielokątrect
- rysuje prostokątsegments
- rysuje odcinkitext
- dodaje teksttitle
- dodaje tytuł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.
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
- histogramHistogram 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
.
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.
# 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
.
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
## [1] 36.38 36.58 36.78 36.98 37.18 37.38 37.58 37.78 37.98 38.18 38.38
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łupkowyWykres 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ć.
df = read.csv('student-por.csv', sep=";", header = TRUE)
table(df$Mjob) # tabela z której tworzymy wykres
##
## at_home health other services teacher
## 135 48 258 136 72
barplot(table(df$Mjob)) # wykres, jako argument przyjmuje twór "macierzopodobny" - w tym wypadku tabelę
Wykres możemy upiększać ustawiając mu kolory oraz przerzucając go na drugi bok.
df = read.csv('student-por.csv', sep=";", header = TRUE)
prop.table(table(df$Mjob)) # za pomocą prop.table możemy stworzyć wykres procentowy
##
## at_home health other services teacher
## 0.20801233 0.07395994 0.39753467 0.20955316 0.11093991
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?
prop.table
. Musimy pamiętać, by przekazać odpowiedni wymiar
(margin
)prop.table(table(df$studytime, df$Mjob), 2) # za pomocą prop.table możemy stworzyć wykres procentowy
##
## at_home health other services teacher
## 1 0.34074074 0.31250000 0.34108527 0.32352941 0.26388889
## 2 0.48888889 0.54166667 0.44961240 0.44117647 0.51388889
## 3 0.13333333 0.10416667 0.15116279 0.16911765 0.16666667
## 4 0.03703704 0.04166667 0.05813953 0.06617647 0.05555556
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
.
barplot(tapply(df$G3, df$Mjob, mean))
boxplot
- wykres pudełkowyProszę nauczyć się odczytywać dane z wykresów pudełkowych.
Boxplot
Oraz przeczytać dowolny artykuł gdziekolwiek na ten temat. Moze być ten:
http://onlinestatbook.com/2/graphing_distributions/boxplots.html
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 skrzypcowyWykres skrzypcowy
https://en.wikipedia.org/wiki/Violin_plot
# install.packages("vioplot") musimy zainstalować pakiet vioplot tworzący wykres skrzypcowy
library(vioplot)
## Ładowanie wymaganego pakietu: sm
## Package 'sm', version 2.2-5.7: type help(sm) for summary information
## Ładowanie wymaganego pakietu: zoo
##
## Dołączanie pakietu: 'zoo'
## Następujące obiekty zostały zakryte z 'package:base':
##
## as.Date, as.Date.numeric
par(mfrow = c(1,2))
vioplot(split(df, df$sex)[[2]]$G3)
vioplot(split(df, df$sex)[[1]]$G3)