Sesija 05: Uvod u analitiku u R: {dplyr} paket

Fidbek se upućuje na goran.milovanovic@datakolektiv.com. Ova sveščica prati kurs Uvod u R programiranje za analizu podataka 2020/21.


U Sesiji 05 bavimo se uvodom u analitiku u programskom jeziku R. Idealan paket za tako nešto je, naravno, {dplyr} - paket koji pruža gramatiku za manipulaciju podacima. Ukoliko ovo zvuči komplikovano, videćete da zapravo nije, a ukoliko imate iskustva sa SQL i relacionim bazama podataka - videćete da sintaksa {dplyr} skoro u potpunosti mapira logiku SQL u R programiranje. To je jedan od paketa bez koga analitičari u R praktično ne počinju svoj posao: library(dplyr). Pored uvoda u {dplyr}, naučićemo kako da iz R pokupimo podatke sa Interneta pomoću jednostavnog read.cvs() poziva, a takođe ćemo videti i neke primere upotrebe funkcionalnog programiranja sa Map() ili Reduce() u R.

0. Reduce() u akciji

Hajde prvo da skinemo neke podatke sa Interneta. Na stranici Inside Airbnb nalaze se neki otvoreni skupovi podataka kompanije Airbnb kakve koriste njihovi analitičari i sa kojima možete da se igrate. Skinućemo nekoliko .csv fajlova sa te stranice:

filename <- "http://data.insideairbnb.com/the-netherlands/north-holland/amsterdam/2021-11-04/visualisations/listings.csv"
amsterdam_data <- read.csv(filename, 
                           header = TRUE,
                           row.names = 1,
                           check.names = FALSE,
                           stringsAsFactors = FALSE)
head(amsterdam_data)
antwerp_data <- read.csv("http://data.insideairbnb.com/belgium/vlg/antwerp/2021-10-28/visualisations/listings.csv", 
                           header = TRUE,
                           row.names = 1,
                           check.names = FALSE,
                           stringsAsFactors = FALSE)
head(antwerp_data)
asheville_data <- read.csv("http://data.insideairbnb.com/united-states/nc/asheville/2021-10-18/visualisations/listings.csv", 
                           header = TRUE,
                           row.names = 1,
                           check.names = FALSE,
                           stringsAsFactors = FALSE)

head(asheville_data)

Potrebno je da spojimo ova tri skupa podataka u jedan. Svi su iste klase, naravno: data.frame. Postoji funkcija u R koja se zove rbind() i ona spaja dva objekta data.frame klase u jedan tako što nastavlja redove jednog na drugi:

amsterdam_antwerp_data <- rbind(amsterdam_data, antwerp_data)
head(amsterdam_antwerp_data)

Naravno, pri spajanju skupova podataka hoćemo da znamo koji su redovi došli iz kog originalnog skupa. Zato ćemo prvo da dodamo svakoj tabeli po jednu kolonu koja karakteriše grad na koji se opservacije odnose:

amsterdam_data$city <- "Amsterdam"
antwerp_data$city <- "Antwerp"
asheville_data$city <- "Asheville"

A sada ćemo da iskoristimo Reduce() da u jednoj liniji koda obavimo spajanje sva tri skupa podataka u jedan sa kojim možemo da nastavimo rad u {dplyr}. Da vidimo koliki su polazni skupovi podataka prvo:

dim(amsterdam_data)
## [1] 5402   18
dim(antwerp_data)
## [1] 1750   18
dim(asheville_data)
## [1] 2563   18

Spajamo sa Reduce():

dataSet <- Reduce(f = rbind, x = list(amsterdam_data, antwerp_data, asheville_data))
dim(dataSet)
## [1] 9715   18

To je to : ) Napomena: Ko zaista želi da nauči da efikasno radi u R, postoji funkcija rbindlist() u paketu {data.table} koja efikasno obavlja ovakvo spajanje objekata data.frame (i data.table) klase u jedan objekat, ali {data.table} definitivno nije uvodni materijal u R.

1. Map() u akciji

Voleo bih da izračunam kovarijanse četiri vektora slučajnih brojeva u R. Evo tih vektora; svi su generisani sa normalne distribucije sa prosekom od 10 i standardnom devijacijom od 2, i svi sadrže 1,000 slučajnih brojeva:

vec1 <- rnorm(1000, mean = 10, sd = 2)
vec2 <- rnorm(1000, mean = 10, sd = 2)
vec3 <- rnorm(1000, mean = 10, sd = 2)
vec4 <- rnorm(1000, mean = 10, sd = 2)
vec_list <- list(vec1, vec2, vec3, vec4)

Napravimo sve kombinacije rednih brojeva (1-4) svih vektora u vec_list sa 2 elementa:

design <- combn(x = 1:4, m = 2)
print(design)
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    1    1    2    2    3
## [2,]    2    3    4    3    4    4

Fino; sad Map():

cov_mat <- Map(cov, vec_list[design[1, ]], vec_list[design[2, ]])
print(cov_mat)
## [[1]]
## [1] 0.09380668
## 
## [[2]]
## [1] -0.215272
## 
## [[3]]
## [1] -0.05850865
## 
## [[4]]
## [1] -0.05067179
## 
## [[5]]
## [1] -0.02658384
## 
## [[6]]
## [1] -0.03556833

Da proverimo: prvo poređenje u našem nacrtu je između prvog i drugog vektora u vec_list, dakle vec1 i vec2:

cov(vec1, vec2)
## [1] 0.09380668

a kroz primenu Map() smo dobili takođe:

print(cov_mat[[1]])
## [1] 0.09380668

2. Uvod u {dplyr}

library(dplyr)
dim(dataSet)
## [1] 9715   18
dataSet <- dataSet %>% 
  dplyr::filter(number_of_reviews > 0)
dim(dataSet)
## [1] 8836   18
dataSet <- dataSet %>% 
  dplyr::select(host_id,
                room_type,
                price,
                minimum_nights,
                number_of_reviews,
                city)
head(dataSet)
table(dataSet$room_type)
## 
## Entire home/apt      Hotel room    Private room     Shared room 
##            6474             101            2231              30

Koja je prosečna cena, medijana cene, i standardna devijacija cena ajtema u Amsterdamu u zavisnosti od room_type:

dataSet %>% 
  dplyr::filter(city == "Amsterdam") %>% 
  dplyr::group_by(room_type) %>% 
  dplyr::summarise(mean_price = mean(price), 
                   med_price = median(price),
                   sd_price = sd(price))
dataSet %>% 
  dplyr::group_by(city, room_type) %>% 
  dplyr::summarise(mean_price = mean(price), 
                   med_price = median(price),
                   sd_price = sd(price),
                   max_price = max(price), 
                   min_price = min(price), 
                   num_obs = n())
dataSet <- dataSet %>% 
  arrange(price)
head(dataSet)

R Markdown

R Markdown je ono što koristimo da bismo razvili ove sveščice. Evo knjige iz koje se može naučiti rad u toj jednostavnoj ekstenziji R: R Markdown: The Definitive Guide, Yihui Xie, J. J. Allaire, Garrett Grolemunds..


Goran S. Milovanović, Data Scientist & Vlasnik, DataKolektiv.
Kontakt: goran.milovanovic@datakolektiv.com. Ovo je besplatan i slobodan softver: GPL v2.0.