6. Vremenske serije

Grafik Time Series za vremenske serije (objekat tipa ts)

Paket ggfortify dozvoljava autoplot-u da automatski crta grafik direktno iz objekta tipa vremenske serije (ts).

# objekat tipa vremenske serije (ts)
library(ggfortify)
theme_set(theme_classic())

autoplot(AirPassengers) + 
  labs(title="AirPassengers") + 
  theme(plot.title = element_text(hjust=0.5))

Grafik vremenske serije iz baze podataka

Koristeći geom_line(), vremenska serija (ili line_chart) se može nacrtati i iz baze podataka. Podeoci x ose se generišu na podrazumevan način. U donjem primeru, podeoci se formiraju tako da se prekidi dešavaju na svakih 10 godina.

Podrazumevna oznaka x ose
theme_set(theme_classic())

data("economics", package = "ggplot2")
library(lubridate)
economics = mutate(economics, returns_perc = c(0, diff(psavert)/psavert[-length(psavert)]))

ggplot(economics, aes(x=date)) + 
  geom_line(aes(y=returns_perc)) + 
  labs(title="Time Series Chart", 
       subtitle="Returns Percentage from 'Economics' Dataset", 
       caption="Source: Economics", 
       y="Returns %")

Grafik mesečnih vremenskih serija

Ako želimo da postavimo sami vremenske intervale (breaks) na x osi, potrebno je da podesimo podeoke i oznake koristeci scale_x_date().

library(lubridate)
theme_set(theme_bw())
data("economics", package = "ggplot2")

# Racunamo % 
economics = mutate(economics, returns_perc = c(0, diff(psavert)/psavert[-length(psavert)]))

economics_m = economics[1:24, ]

# podesavamo podeoke i oznake za x osu
lbls = paste0(month.abb[month(economics_m$date)], " ", year(economics_m$date))
brks = economics_m$date

ggplot(economics_m, aes(x=date)) + 
  geom_line(aes(y=returns_perc)) + 
  labs(title="Monthly Time Series", 
       subtitle="Returns Percentage from Economics Dataset", 
       caption="Source: Economics", 
       y="Returns %") + 
  scale_x_date(labels = lbls, 
               breaks = brks) +  # namestamo na mesecne podeoke i oznake
  theme(axis.text.x = element_text(angle = 90, vjust=0.5),
        panel.grid.minor = element_blank())  

Grafik godišnjih vremenskih serija

library(lubridate)
theme_set(theme_bw())

economics_y = economics[1:90, ]

# podeoci i oznake za x osu
brks = economics_y$date[seq(1, length(economics_y$date), 12)]
lbls = year(brks)

ggplot(economics_y, aes(x=date)) + 
  geom_line(aes(y=returns_perc)) + 
  labs(title="Yearly Time Series", 
       subtitle="Returns Percentage from Economics Dataset", 
       caption="Source: Economics", 
       y="Returns %") +
  scale_x_date(labels = lbls, 
               breaks = brks) + 
  theme(axis.text.x = element_text(angle = 90, vjust=0.5),  # rotiramo tekst na x osi
        panel.grid.minor = element_blank())  

Grafik višestrukih vremenskih serija za “dugi” format podataka: Podaci u jednoj koloni

U ovom primeru, pravimo ggplot iz “dugog” formata podataka. To znači da se imena kolona i odgovarajuće vrednosti svih kolona smeštaju samo u 2 promenljive (variable i value redom). Ako bismo želeli da transformišemo ovu bazu u “široki” format, dobili bismo economics bazu.

U primeru dole, geom_line() se crta za kolonu value, a aes(col) je podešen na variable. Na ovaj način, samo jednim pozivom geom_line() crtaju se obojene linije, po jedna za svaku jedinstvenu vrednost u koloni variable. Funkcija scale_x_date() menja podeoke i oznake na x osi, a scale_color_manual menja boju linija.

data(economics_long, package = "ggplot2")
head(economics_long)
## # A tibble: 6 x 4
## # Groups:   variable [1]
##   date       variable value  value01
##   <date>     <fct>    <dbl>    <dbl>
## 1 1967-07-01 pce       507. 0       
## 2 1967-08-01 pce       510. 0.000266
## 3 1967-09-01 pce       516. 0.000764
## 4 1967-10-01 pce       513. 0.000472
## 5 1967-11-01 pce       518. 0.000918
## 6 1967-12-01 pce       526. 0.00158
library(lubridate)
theme_set(theme_bw())

df = filter(economics_long, variable %in% c("psavert", "uempmed"))
df = filter(df, year(date) %in% c(1967:1981))

# oznake i podeoci na x osi
brks = df$date[seq(1, length(df$date), 12)]
lbls = year(brks)

ggplot(df, aes(x=date)) + 
  geom_line(aes(y=value, col=variable)) + 
  labs(title="Time Series of Returns Percentage", 
       subtitle="Drawn from Long Data format", 
       caption="Source: Economics", 
       y="Returns %", 
       color=NULL) + 
  scale_x_date(labels = lbls, breaks = brks) +  # menjamo na mesecne ticks i oznake
  scale_color_manual(labels = c("psavert", "uempmed"), 
                     values = c("psavert"="#00ba38", "uempmed"="#f8766d")) +  # boja linija
  theme(axis.text.x = element_text(angle = 90, vjust=0.5, size = 8),  # rotiramo tekst na x osi
        panel.grid.minor = element_blank())  # iskljucujemo manju mrezu

Grafik višestrukih vremenskih serija za “široki” format podataka: Podaci u više kolona u bazi

Iako ispod prikazana slika izgleda kao prethodna, pristup za konstruisanje je drugačiji. Ako prikazujemo vremenske serije iz “široko” formatiranih podataka, moramo da crtamo svaku liniju ručno, pozivajući geom_line() jednom za svaku liniju.

library(lubridate)
theme_set(theme_bw())

df = select(economics, date, psavert, uempmed)
df = filter(df, year(date) %in% c(1967:1981))

brks = df$date[seq(1, length(df$date), 12)]
lbls = year(brks)

ggplot(df, aes(x=date)) + 
  geom_line(aes(y=psavert, col="psavert")) + 
  geom_line(aes(y=uempmed, col="uempmed")) + 
  labs(title="Time Series of Returns Percentage", 
       subtitle="Drawn From Wide Data format", 
       caption="Source: Economics", y="Returns %") +
  scale_x_date(labels = lbls, breaks = brks) +  
  scale_color_manual(name="", 
                     values = c("psavert"="#00ba38", "uempmed"="#f8766d")) +  
  theme(panel.grid.minor = element_blank())  

Stacked Area Chart

Area Chart se obično koristi kada:

  1. Želimo da opišemo kako se veličina ili zapremina (a ne nešto kao cena) menja tokom vremena.

  2. Imamo mnogo tačaka (podataka). Za veoma malo tačaka, bolje je crtanje bar chart-a.

  3. Želimo da prikažemo doprinos pojedinačnih komponenti. Ovo se može iscrtati pomoću geom_area koja radi veoma slično kao geom_line. Ali postoji jedna važna stvar koju treba napomenuti. Podrazumevano, svaki geom_area() počinje od dna y ose (sto je obicno 0), međutim, ako želimo da prikažemo doprinos pojedinačnih komponenti, želimo da se geom_area() slaže iznad prethodne komponente, a ne na dnu samog grafika. Dakle, moramo dodati donje slojeve kada podešavamo y u geom_area().

U donjem primeru, postavili smo y = psavert + uempmed za najvišu geom_area().

Koliko god se čini da grafik lepo izgleda, treba voditi računa da lako može postati komplikovano i neinterpretabilno ako ima previše komponenti.

library(lubridate)
theme_set(theme_bw())

df = select(economics, date, psavert, uempmed)
df = filter(df, year(date) %in% c(1967:1981))

brks = df$date[seq(1, length(df$date), 12)]
lbls = year(brks)

ggplot(df, aes(x=date)) + 
  geom_area(aes(y=psavert+uempmed, fill="psavert")) + 
  geom_area(aes(y=uempmed, fill="uempmed")) + 
  labs(title="Area Chart of Returns Percentage", 
       subtitle="From Wide Data format", 
       caption="Source: Economics", 
       y="Returns %") +  # title and caption
  scale_x_date(labels = lbls, breaks = brks) +  # menjamo na mesecno 
  scale_fill_manual(name="", 
                    values = c("psavert"="#00ba38", "uempmed"="#f8766d")) +  # boja linija
  theme(panel.grid.minor = element_blank())  # iskljucujemo manju mrezu

Calendar Heatmap

Kada želimo da vidimo varijacije, posebno uspone i padove, vrednosti kao što npr. je cena akcija, na samom kalendaru, koristimo Calendar heatmap. Ona vizuelno naglašava varijaciju tokom vremena umesto samih vrednosti.

Ovo se može implementirati korišćenjem geom_tile. Međutim, dobijanje u pravom formatu ima više veze sa pripremom podataka, nego sa samim crtanjem grafika.

library(scales)
library(zoo)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
df = read.csv("https://raw.githubusercontent.com/selva86/datasets/master/yahoo.csv")
df$date = as.Date(df$date)  # format datum
df = filter(df, year >= 2012)  # filtriramo godine

df = mutate(df, yearmonth = as.yearmon(date))
df = mutate(df, yearmonthf = factor(yearmonth))


df = ddply(df,.(yearmonthf), transform, monthweek=1+week-min(week))  # racunamo redni broj nedelje u mesecu
df = select(df, year, yearmonthf, monthf, week, monthweek, weekdayf, VIX.Close)
head(df)
##   year yearmonthf monthf week monthweek weekdayf VIX.Close
## 1 2012   Jan 2012    Jan    1         1      Tue     22.97
## 2 2012   Jan 2012    Jan    1         1      Wed     22.22
## 3 2012   Jan 2012    Jan    1         1      Thu     21.48
## 4 2012   Jan 2012    Jan    1         1      Fri     20.63
## 5 2012   Jan 2012    Jan    2         2      Mon     21.07
## 6 2012   Jan 2012    Jan    2         2      Tue     20.69
ggplot(df, aes(monthweek, weekdayf, fill = VIX.Close)) + 
  geom_tile(colour = "white") + 
  facet_grid(year~monthf) + 
  scale_fill_gradient(low="red", high="green") +
  labs(x="Week of Month",
       y="",
       title = "Time-Series Calendar Heatmap", 
       subtitle="Yahoo Closing Price", 
       fill="Close")

Seasonal plot

Kada radimo sa vremenskim serijama klase ts ili xts, možemo videti sezonske komponente crtanjem sezonskog grafika, koristeći ggseasonplot iz paketaforecast . U nastavku je prikazan primer u kome koristimo serije AirPassengers i nottem.

library(forecast)
theme_set(theme_classic())

# Izdvajamo prvih 5 godina
nottem_small = window(nottem, start=c(1920, 1), end=c(1925, 12))  

ggseasonplot(nottem_small) + labs(title="Seasonal plot: Air temperatures at Nottingham Castle")

ggseasonplot(AirPassengers) + labs(title="Seasonal plot: International Airline Passengers")

Možemo videti rastući trend (povećanje saobraćaja tokom godina) u AirPassengers sa sezonskim obrascem koji se ponavlja, dok Nottingham ne pokazuje porast temperature tokom godina, ali definitvno prati sezonski obrazac.

7. Klasteri

Hierarchical Dendrogram

library(ggdendro)
theme_set(theme_bw())

hc = hclust(dist(USArrests), "ave")  # hijerarhijsko klasterovanje

ggdendrogram(hc, rotate = TRUE, size = 2)

Klasteri

Možemo izračunati glavne komponente i nacrtati scatterplot koristeći PC1 i PC2 kao x i y ose.

Funkcija geom_encircle() se koristi za zaokruživanje željenih grupa, i to tako što se podskup podataka koji sadrži samo opservacije (redove) navede kao data argument.

library(ggalt)
library(ggfortify)
theme_set(theme_classic())

# Racunamo glavne komponente
df = iris[c(1, 2, 3, 4)]
pca_mod = prcomp(df)  # izdvajanje glavnih komponenti

# Baza glavnih komponenti
df_pc = data.frame(pca_mod$x, Species=iris$Species)  # baza glavnih komponenti
df_pc_vir = df_pc[df_pc$Species == "virginica", ]  # vrsta 'virginica'
df_pc_set = df_pc[df_pc$Species == "setosa", ]  # vrsta 'setosa'
df_pc_ver = df_pc[df_pc$Species == "versicolor", ]  # vrsta 'versicolor'
 
ggplot(df_pc, aes(PC1, PC2, col=Species)) +  
 geom_point(aes(shape=Species), size=2) +   # draw points
  labs(title="Iris Clustering", 
       subtitle="With principal components PC1 and PC2 as X and Y axis",
       caption="Source: Iris") + 
  coord_cartesian(xlim = 1.2 * c(min(df_pc$PC1), max(df_pc$PC1)), 
                  ylim = 1.2 * c(min(df_pc$PC2), max(df_pc$PC2))) +   # menjamo granice osa
  geom_encircle(data = df_pc_vir, aes(x=PC1, y=PC2)) +   
  geom_encircle(data = df_pc_set, aes(x=PC1, y=PC2)) + 
  geom_encircle(data = df_pc_ver, aes(x=PC1, y=PC2))

8. Prostorni

Paket ggmap pruža mogućnosti za interakciju sa Google Maps api-jem i dobijanje koordinata (geografske dužine i širine) za mesta koja želimo da iscrtamo. Primer koji sledi prikazuje razne karte za grad Čenaj (Indija), zaokružujući neka od mesta. Koristili smo funkciju geocode() da dobijemo kooridnate ovih mesta i qmap() da dobijemo mape. Tip mape je određen vrednošću koja je postavljena u maptype.

Takođe, možemo zumirati mapu korišćenjem argumenta zoom. Podrazumevano je 10 (pogodno za velike gradove). Smanjujemo ovaj broj (do 3), ako želimo da smanjimo, a povećavamo do 21, što je pogodno ako želimo da vidimo zgrade.

library(ggmap)
library(ggalt)

# Koordinate Cenaja
chennai =  geocode("Chennai")   # geografske sirine i duzine

# Mapa
# Google Satellite Map
chennai_ggl_sat_map = qmap("chennai", zoom=12, source = "google", maptype="satellite")  

# Google Road Map
chennai_ggl_road_map = qmap("chennai", zoom=12, source = "google", maptype="roadmap")  

# Google Hybrid Map
chennai_ggl_hybrid_map = qmap("chennai", zoom=12, source = "google", maptype="hybrid")  

# Open Street Map
chennai_osm_map = qmap("chennai", zoom=12, source = "osm")   

# Koordinate mesta u Cenaju
chennai_places = c("Kolathur",
                    "Washermanpet",
                    "Royapettah",
                    "Adyar",
                    "Guindy")

places_loc = geocode(chennai_places)  # geografske sirine i duzine


# Open Street Map 
chennai_osm_map + geom_point(aes(x=lon, y=lat),
                             data = places_loc, 
                             alpha = 0.7, 
                             size = 7, 
                             color = "tomato") + 
                  geom_encircle(aes(x=lon, y=lat),
                                data = places_loc, size = 2, color = "blue")
# Google Road Map
chennai_ggl_road_map + geom_point(aes(x=lon, y=lat),
                                  data = places_loc, 
                                  alpha = 0.7, 
                                  size = 7, 
                                  color = "tomato") + 
                       geom_encircle(aes(x=lon, y=lat),
                                     data = places_loc, size = 2, color = "blue")
# Google Hybrid Map 
chennai_ggl_hybrid_map + geom_point(aes(x=lon, y=lat),
                                     data = places_loc, 
                                     alpha = 0.7, 
                                     size = 7, 
                                     color = "tomato") + 
                          geom_encircle(aes(x=lon, y=lat),
                                        data = places_loc, size = 2, color = "blue")