II. Práca s datami / základné popisné
charakteristiky v R
Program R (dostupný pod GNU GPL licenciou) je k dispozícii k
stiahnutiu (free of charge) na adrese:
https://www.r-project.org
K dispozícii sú distribúcie s priamou podporou pre OS Windows, Linux
aj Macintosh.
Základnú inštaláciu programu R je možné jednoducho rozšíriť pomocou
dodatočných knižníc (balíčkov), ktoré sú k dispozícii na viacerých
online repozitároch (zoznam hlavných repozitárov je na adrese
https://cran.r-project.org/mirrors.html).
Jednotlivé R knižnice sú tvorené samotnými užívateľmi softwaru R a ich
správne fungovanie nie je garantované – je preto potrebná určitá
opatrnosť a hlavne aktívne premýšľanie pri ich používaní a implementácii
jednotlivých funkcii.
Pre užívateľov programu R sú k dispozícii aj rôzne grafické
rozhrania, ktoré je možne dodatočne nainštalovať a umožňujú (v určitých
smeroch) jednoduchšiu a prehľadnejšiu prácu. Najznámejší a pravdepodobne
aj najviac používaný je
RStudio.
Užitočné materiály pre prácu so štatistickým programom
R
-
Bína, V., Komárek, A. a Komárková, L.: Jak na jazyk R.
(PDF súbor)
-
Komárek, A.: Základy práce s R. (PDF
súbor)
-
Kulich, M.: Stručný úvod do R. (PDF
súbor)
-
Scott, T.: An Introduction to R
(PDF súbor)
-
De Vries, A. a Meys, J.: R for Dummies. (ISBN-13: 978-1119055808)
1. Práca s datovými
súbormi
V programe R je štandardne k dispozícii množstvo vzorových datových
súborov rôzných formátov a typov. Zoznam týchto datových suborov sa
získa príkazom data()
. Na konkrétny datový súbor sa
následne odkazuje pomocou mena príslušného datového súboru.
rm(list = ls())
data() ### zobrazi zoznam datovych suborov, ktore su v Rku k dispozicii
Orange
Ďalšie vzorové data lze získať inštaláciou dodatočných knižnic
(pomocou príkazu install.packages()
– viď help pre
konkrétnu implementáciu). Zoznam datových súborov z konkrétnej knižnice
(package) lze získať pomocou dodatočného parameteru pri volaní funkcie
package = NULL
. Pre zobrazenie zoznamu datových súborov
ubsiahnutých v knižnici lattice slúži potom príkaz
data(package = "actuar")
data(package = "lattice")
Reálne datové súbory bývajú prevažne reprezentované prostredníctvom
tabuliek (tzv. datových matíc) s množstvom ríadkov (väčšinou jednotlivé
pozorovania) a stĺpcov (väčšinou zaznamenané premenné). Nie vždy je
možné celkový datový súbor zobraziť na obrazovke, preto je užitočné
poznať niektoré príkazy, prostredníctvom ktorých sa o datach dozvieme
aspoň tie podstatné informácie. V praxi sa ale bežne stane, že samotné
data je potrebné výrazne upraviť/modifikovať/prispôsobiť tak, aby bolo
možné s nimi efektívne pracovať (t.j., aplikovať nejaký konkrétny
pravdepodobnostný model – napr. dvojvýberový štatistický test). Príprava
datového súboru je teda prvý a základný krok pred samotnou štatistickou
analýzou.
Ako názorná ilustrácia môže slúžiť nasledujúci príklad:
test.data <- read.table("http://www.karlin.mff.cuni.cz/~maciak/NMSA407/NMSA407-1617-HW1.txt", header=T)
dim(test.data) ### velkost datoveho suboru: pocet pozorovani a pocet sledovanych premennych
str(test.data) ### struktura a typ jednotlivych premennych
head(test.data) ### niekolko prvych pozorovani
summary(test.data) ### zakladne popisne charakteristiky polohy
V prípade, že pracujeme pouze s jednym datovým súborom, je možne
odkazovať sa na jednotlivé premenné aj pomocou príslušného názvu
premenných. Potrebný je príkaz attach()
(záleží tiež od
konkrétnej verzie programu R), ktorý volanie prostredníctvom názvu
premenných umožní. Porovnajte výstup dvoch nasledujúcich časti
zdrojového kódu:
table(hitchhikers)
table(test.data$hitchhikers)
a
attach(test.data)
table(hitchhikers)
S jednotlivými premennými môžeme v Rku následne jednoducho pracovať a
podľa potreby si ich upravovať, prípadne definovať nové premenné (resp.
rôzne datové podsúbory). Užitočný príkaz pre manipuláciu s premennými a
definíciu nových premenných je príkaz transform()
.
test.data <- transform(test.data, driverCZ = factor(1*(driverGender == "male") + 2*(driverGender == "female"), labels = c("M", "Z")))
test.data <- transform(test.data, distance01 = factor(1*(travelDistance != "> 500km") + 2*(travelDistance == "> 500km"), labels = c("short_trip", "long_trip")))
test.data <- transform(test.data, waitingTimeHours = ceiling(waitingTime/60))
head(test.data)
## hitchhikers travelDistance driverGender country waitingTime carNumber
## 1 two guys < 50km male CZ 10 NA
## 2 two guys 100 - 500 male other 34 NA
## 3 two guys 100 - 500 female D 30 NA
## 4 two guys 100 - 500 male D 45 NA
## 5 two guys < 50km male D 30 NA
## 6 two guys < 50km male D 45 NA
## dayNight driverCZ distance01 waitingTimeHours
## 1 day M short_trip 1
## 2 day M short_trip 1
## 3 night Z short_trip 1
## 4 day M short_trip 1
## 5 day M short_trip 1
## 6 day M short_trip 1
table(test.data$driverCZ, test.data$driverGender)
##
## female male
## M 0 157
## Z 23 0
table(test.data$waitingTimeHours, test.data$waitingTime)[,1:20]
##
## 0 1 2 3 4 5 6 7 8 10 12 13 14 15 16 18 19 20 22 25
## 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 1 0 5 4 3 1 17 2 3 1 13 2 2 1 8 1 2 1 9 2 8
## 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Následujúci výstup ale nepôsobí ideálnym dojmom. Intuitívne by sme
asi očakávali, že zoradenie jednotlivých kategórii bude logické, keďže
sa jedná o tzv. ordinálny faktor (premennú s diskrétnymi, ale
ordinalnými hodnotami).
table(test.data$distance01, test.data$travelDistance)
##
## < 50km > 500km 100 - 500 50 - 100
## short_trip 98 0 49 25
## long_trip 0 8 0 0
V programe R funguje automatické zoradenie faktorových úrovni podľa
abecedy (vysvetlené a vyjadrené jednoducho). Rozumnejšie (intuitivne
požadované) usporiadanie tabuľky získame dodatočným príkazom:
test.data$travelDistance <- ordered(test.data$travelDistance, levels = c("< 50km", "50 - 100", "100 - 500", "> 500km"))
table(test.data$distance01, test.data$travelDistance)
##
## < 50km 50 - 100 100 - 500 > 500km
## short_trip 98 25 49 0
## long_trip 0 0 0 8
Všimnite si, že na pôvodné premenné je naďalej možné odkazovať sa
pomocou ich názvu, ale nové premenné týmto spôsobom sprístupnené nie sú.
Dokonca ani modifikácia pôvodných premenných v datovej tabuľke nebude
pri volaní samotnej premennej zohľadnená.
Z praktického hľadiska je vždy výhodnejšie odkazovať sa na premenné
pomocou odkazu na konkrétny datový súbor – väčšinou totiž pracujeme s
viacerými datovými súbormi naraz (tak to aspoň býva na začiatku práce,
pri príprave finálneho datového súboru) a zabráni sa takto nechceným
omylom, ktoré často ani nemusíme zaregistrovať. V prípade, že pracujeme
pouze s jedným datovým súborom, postači opätovne zavolať príkaz
attach(test.data)
V programe R môžeme pracovať s datovými súbormi rôznych formátov a
rôznych typov. Najčastejšie používané príkazy pre načítanie datového
súboru z disku sú read.table()
a read.csv()
. K
načítaniu datového súboru, ktorý je typický pre program R (súbor typu
.RData) slúži príkaz load()
. Hlavne prvé dva príkazy
používajú množstvo rôznych parametrov, ktorými sa da presne špecifikovať
konkrétny spôsob, ako data načítať (často používané parametre sú napr.
header \(=\) , sep \(=\) , dec \(=\) , na.string \(=\) , as.is \(=\) , row.names \(=\) , col.names \(=\) a mnoho ďalších).
Porovnajte napr. nasledujúce dva príkazy:
tempData <- read.table("testData.txt", header = T, sep = ";", dec = ".")
tempData <- read.table("testData.txt", header = F, sep = ".", dec = ";", skip = 1)
Užitočné
-
Pre správne načítanie datového súboru je nutné poznať data a vedieť, ako
sú uložené a akým spôsobom sú reprezentované (napr. ako sú označené
chýbajúce pozorovania, aký znak sa používa na oddelenie desatinných
miest, a pod.);
-
Užitočné príkazy pre prácu sa datami a manipuláciu s premennými sú napr.
class()
, factor()
, as.factor()
,
as.character()
, as.numeric()
a mnohé ďalšie
(viď napr. help k uvedeným funkciám). Použijte help k niektorým z
uvedených príkazov a podívajte sa na spôsob ich implemenácie, ilustračné
príklady aplikácie, prípadne ďalšie súvisiace funkcie v referenciách;
-
Pomocou dodatočných knižníc je môžne načítať aj súbory z Excelu
(príkaz read_excel()
z knižnice
library("readxl")
), z SQL databázy (knižnica
library(dbplyr)
) mnoho ďalších typov súborov, vrátane
obrázkov, videí, alebo mp3 súborov;
Napr. načítanie
obrázku:
library("jpeg")
foto <- readJPEG("foto.jpg")
class(foto)
dim(foto)
plot.new()
rasterImage(foto,0,0,1,1)
-
Pre program R existuje množstvo dodatočných knižníc, ktoré umožňujú
načítať rôzne iné súbpry - napr. Excel tabuľku z xls alebo
xlsx súborov, data z SQL databázy, ale aj obrázkove, filmové, či
zvukové súbory. Ďalšie knižnice sú určené pre načítanie a prácu s
rozsiahlými datami (napr. data v rozsahu desiatok GB).
-
Pomocou dodatočných knižníc je možné v programe R umožniť priamu
spoluprácu aj so softwarom tretích strán. Napr. baliček
SWAT
umožňuje prepojenie programu R a iného štatistického
programu SAS,
balíček Rmosek
umožní prepojenie programu R a
optimalizačného toolboxu mosek,
knižnica reticulate
umožnuje prepojenie Rka a
Pythonu, knižnica
rJava
umožní používať v programe R programovací jazyk
Java, knižnica
ROracle
umožňuje prepojiť program R s databázovým systémom
Oracle a existuje mnoho ďalších
možnosti a k ním príslušných Rkových balíčkov.
2. Regular expressions in
R
Ako bolo uvedené už v prvom seminári, program R umožňuje prácu s tzv.
“regular expressions” (regulárnymi výrazmi). Regulárne výrazy sú
výstižným a flexibilným nástrojom na popis rôznych vzorov (patterns) v
reťazcoch znakov. Práca s regulárnymi výrazmi často ulahčuje a
zefektivňuje prácu s datami - hlavne pri príprave dat k analýze (vid
help ?regex
).
Zaujímavé ukážky a ilustračné príklady napríklad tu:
https://cran.r-project.org/web/packages/stringr/vignettes/regular-expressions.html
Jednoduchá illustrácia:
grep("o", c("hallo", "world"))
grepl("o", c("hallo", "world"))
sub("o", "O", c("hallo", "world"))
Užitočné
-
Základné príkazy:
grep()
, grepl()
,
sub()
, gsub()
, match()
,
pmatch()
, regexpr()
, gregexpr()
a
mnoho ďalších;
-
Vyhľadávanie v texte:
str_detect()
,
str_extract()
, str_match()
,
str_subset()
;
-
Dátum a čas:
strptime()
, date()
,
as.Date()
, as.POSIXlt()
,
POSIXct()
;
-
Vypisovanie:
paste()
, strsplit()
,
cat()
;
3. Základné popisné charakteristiky /
exploratívna analýza
Na jednotlivé premenné sa môžeme v programe R odkazovať priamo
pomocou ich názvu. Môžeme takto spočítať základne empirické
charakteristiky pre jednotlivé premenné (tzv. výberové verzie
teoretických (neznámych) charakteristík). V programe R je k tomu celá
rada rôznych (intuitivne implementovaných) funkcii: mean()
,
median()
, min()
, max()
,
sd()
, var()
, quantile()
, a mnoho
ďalších. Pomocou helpu k jednotlivých príkazom naštudujte, k čomu
jednotlivé funkcie slúžia, ako sú v R implementované a nájdite ďalšie
užitočné funkcie, ktoré sú vhodné pre základnú štatisticku analýzu
dat.
mean(test.data$waitingTime)
Užitočný je aj samotný príkaz summary()
, avšak ten
poskytuje pouze popisné charakteristiky pre polohu (t.j., výberový
priemer, výberový médian, výberové kvartily) a neposkytuje žiadnu
informáciu o variabilite dat (napr. výberový rozptyl, výberová
směrodatná odchýlka, výberové mezikvartilové rozpětí a pod.). Z tohto
dôvodu nie je použitie príkazu summary()
postačujúce a je
nutné doplniť ho o aspoň nejakú informáciu o volatilite.
Analogicky, ako v prípade vektorov a matíc, môžeme odkazovať len na
určitú časť datového súboru a spočítať empirické charakteristiky len pre
konkrétnu (pod)skupinu:
mean(test.data$waitingTime[test.data$driverGender == "male"])
mean(test.data$waitingTime[test.data$driverGender == "female"])
Popisné charakteristiky je možné štrukturovať v závislosti na
príslušnosti k nejakej skupine (konkrétna úroveň nejakéj faktorovej
premennej).
with(test.data, tapply(waitingTime, driverCZ, summary))
with(test.data, tapply(waitingTime, country, summary))
alebo dokonca vytvárať vlastné špecifické výstupy pomocou vlastných
pred-definovaných funkcii:
F1 <- function(x){
temp <- round(c(min(x), mean(x), max(x), var(x), quantile(x, prob = 0.9)), 3)
names(temp) <- c("Minimum", "Priemer", "Maximum", "Rozptyl", "90% kvantil")
return(temp)
}
with(test.data, tapply(waitingTime, driverCZ, F1))
## $M
## Minimum Priemer Maximum Rozptyl 90% kvantil
## 0.000 49.223 360.000 3851.200 120.000
##
## $Z
## Minimum Priemer Maximum Rozptyl 90% kvantil
## 1.000 67.696 720.000 22651.676 110.000
U kategorických (resp. faktorových) premenných nie je štandardné
uvádzať klasické výberové popisné charakteristiky. Namiesto toho je
vhodne uviesť absolútne a relatívne počty v jednotlivých
kategóriach.
table(test.data$country) ## absolutne pocty
##
## CZ D ES EST F FIN other P PL RUS
## 63 11 11 9 32 16 14 10 6 8
table(test.data$country)/length(test.data$country) ## relativne pocty
##
## CZ D ES EST F FIN other
## 0.35000000 0.06111111 0.06111111 0.05000000 0.17777778 0.08888889 0.07777778
## P PL RUS
## 0.05555556 0.03333333 0.04444444
Prehľadnejšia forma zápisu:
round(table(test.data$country)/length(test.data$country), 2)
Prípadne viac štrukturované tabuľky vzhľadom k viacerým kategorickým
premenným:
with(test.data, tapply(driverCZ, hitchhikers, table))
prrípadne relatívne počty, ktoré bývajú na prvý pohľad viac
výpovedné:
F2 <- function(x){
temp <- format(round(table(x)/length(x), 2), nsmall = 2)
return(temp)
}
with(test.data, tapply(driverCZ, hitchhikers, F2))
## $`single guy`
## x
## M Z
## "0.90" "0.10"
##
## $`two guys`
## x
## M Z
## "0.78" "0.22"
Užitočné
-
Pomocou helpu sa podívajte na príkaz
subset()
a vyskúšajte,
ako funguje;
-
Pomocou helpu naštudujte, k čomu slúžia funcie
apply()
,
tapply()
, lapply()
, aggregate()
a
by()
;
-
Užitočné príkazy pre prácu s datami sú aj
order()
a
sort()
;
-
Použijte tieto funkcie v súvislosti s datovým súborom ‘test.data’ a
pomocou nich spočítajte niektoré empirické charakteristiky;
-
V pripade, že pracujeme v programe R len s jednym datovým súborom, je
možné prácu (resp. implementáciu príkazov) mierne zjednodušiť - pomocou
príkazu
attach(test.data)
. V prípade, že takto zprístupnene
premenné už neplánujeme využívať, je dobre využiť komplementárny príkaz
detach()
.
-
Je dôležité správne pochopiť fungovanie Rka a odkazovanie na premenné po
použití príkazu
attach()
. Program R totiž zprístupní
premenné v stave, v akom sa v momente volania príkazu
attach()
aktuálne nachádzaju v data.frame. Akýkoľvek
následný zásah do data.framu a zmena hodnôt v ňom, nebude reflektovaná
ak sa na premennú odkážeme pomocou jej názvu a nie priamo cez odkaz na
data.frame;
4. Príprava a programovanie vlastných
skriptov
Štatistický program R slúži aj ako samostatný programovací jazyk:
pomocou tohto programu je možné naprogramovať takmer akúkoľvek úlohu. Je
pri tom užitočné poznať rôzne nástroje a konkrétne funkcie, ktoré k
tomuto účelu môžu poslúžiť (napr. implementácia cyklov for a
while, alebo overovanie podmienok pomocou if).
-
for cyklus:
for (i in 1:10){
print(1:i)
}
-
while cyklus:
i <- 1
while (i < 10){
print(1:i)
i <- i + 1
}
-
overovanie podmienky pomocou if
N <- rpoiss(1)
if (N %% 2 == 0){
print("Sude cislo")
} else {
print("Liche cislo")
}
-
rozlíšovanie prípadov pomocou else if
if (x < 0) {
print("Zaporne cislo")
} else if (x > 0) {
print("Kladne cislo")
} else
print("Nula")
Pri používaní cyklov je dôležité dôsledne skontrolovať skript - môže
sa totiž veľmi jednoducho stáť, že program R neúmyselne zacyklíme. V
takom prípade je dobré poznať klávesovú skratku CTR + C (v konzole
programu R), prípadne ESC v interface RStudio.
Uvedené cykly môžu byť užitočné napr. pri skúmaní dat, počítaní
popisných charakteristík pre jednotlivé premenné a podobne.
vars <- names(test.data) ### premenne v datach
Nvars <- vars[c(5,6)]
for (var in Nvars){
print(paste("Popisne charakteristiky pre promennu", var, sep = " "))
print(F1(test.data[!is.na(test.data[, var]), var]))
print("-------------------------------------------------------")
}
Jednotlivé výstupy ale dostaneme aj samostatne pomocou dvojice
príkazov:
F1(test.data[, c("waitingTime")])
F1(test.data[!is.na(test.data[, "carNumber"]), "carNumber"])
Vo väčšine prípadov je možné požadované riešenie (požadovaný výstup)
získať aj bez pomoci cyklov, pouze s využitím štandardne
implementovaných R-kových príkazov a funkcii.
Užitočné
-
Jednotlivé príkazy je možné v programe R vzájomne kombinovať a vytvárať
z nich komplexné Rkové skripty. K dispozícii je samozrejme mnoho ďalších
nástrojov určených k pokročilému programovaniu (viď napr. help a rôzne
tutoriály).