Poglavje 1 Slovnica ravnanja s podatki
Pri sistematičnem delu s podatki je zelo pomembna berljivost in preglednost programske kode. Pri delu velikokrat delimo svojo programsko kodo z drugimi strokovnjaki, zato je zaželjeno, da je koda pregledna in razumljiva. Lahko se tudi zgodi, da imamo težave z razumevanjem svoje starejše kode. Zaradi tega je smiselno, da stremimo k čimvečji konsistentnosti in preglednosti. Na dolgi rok s tem prihranimo čas -- s konsistentno uporabo enakih ukazov postanemo bolj učinkoviti, prav tako pa lažje prenesemo programsko kodo iz enega problema na drugega. Naša programska koda je s tem bolj robustna in ponovljiva, kar je pomembno iz vidika iskanja napak v analizah. Dober primer konsistentnosti in razumljivosti za sporazumevanje je naraven jezik -- v kolikor dve osebi govorita enak jezik se bosta brez težav sporazumevali. Lahko si predstavljate, da ne boste imeli težav z razumevanjem teksta v slovenščini, če se bo avtor držal slovničnih in pravopisnih pravil. Tako kot se pri naravnem jeziku držimo določenih pravil, lahko podobno dosežemo tudi s programskim jezikom.
V tem predavanju se bomo osredotočili na temeljne operacije, ki jih izvajamo nad podatki. Te operacije so nepogrešljive pri vsaki analizi:
- izbira podmnožice vrstic,
- izbira podmnožice stolpcev,
- dodajanje stolpcev, ki so lahko izpeljani iz obstoječih stolpcev,
- urejanje razpredelnice glede na vrednosti stolpcev,
- povzemanje razpredelnic, na primer povprečja in vsote.
Paket dplyr vsebuje funkcije, ki nam v primerjavi z osnovno različico R-ja, te operacije olajšajo. Temelji na t. i. slovnici ravnanja s podatki (ang. grammar of data manipulation), ki programsko kodo pretvori v nekaj podobnega naravnemu jeziku.
Pri slovnici ravnanja s podatki poznamo 5 osnovnih glagolov, s katerimi preoblikujemo podatke. Vsak glagol ustreza eni izmed temeljnih operacij, ki smo jih omenili zgoraj. Programska koda se potem bere podobno kot naravni jezik -- glagoli programskemu jeziku povedo, kaj naj s podatki naredi. Ti glagoli so implementirani v obliki funkcij:
filter()
Izbira podmnožice vrstic glede na izbrane pogoje.select()
Izbira podmnožice stolpcev, glede na imena stolpcev.mutate()
Dodajanje stolpcev, ki so lahko izpeljani iz obstoječih stolpcev.summarise()
Povzemanje podatkov v razpredelnici.arrange()
Urejanje razpredelnice.
V tem predavanju bomo bolj podrobno spoznali vsakega izmed teh glagolov. Po tem pa si bomo ogledali še dva uporabna povzetka -- povzemanje po vrsticah in povzemanje po stolpcih.
1.1 Priprava
V pripravi se bomo naučili osnovnih klicev petih glagolov iz slovnice ravnanja s podatki. Hkrati bomo primerjali osnovno različico R-ja z uporabo paketa dplyr. Pripravimo podatke:
library(tidyverse) # Nalozimo celotno zbirko paketov tidyverse.
df <- data.frame(
ime = c("Maja", "Ales", "Tom", "Barbara", "Simon", "Tina"),
spol = c("z", "m", "m", "z", "m", "z"),
starost = c(23, 54, 21, 35, 53, 21),
visina = c(170, 180, 192, 168, 177, 182)
)
S funkcijo filter()
izberemo podmnožico vrstic v razpredelnici glede na izbrane pogoje. Izberimo ženske nižje od 180 centimetrov.
# Osnovni R:
df[df$spol == "z" & df$visina < 180, ]
## ime spol starost visina
## 1 Maja z 23 170
## 4 Barbara z 35 168
# dplyr:
filter(df, spol == "z", visina < 180)
## ime spol starost visina
## 1 Maja z 23 170
## 2 Barbara z 35 168
Opazimo, da z uporabo dplyr ni potrebno vsakič pisati df$
pred imenom spremenljivke. Tukaj gre za t. i. maskiranje podatkov (ang. data masking). Več o tem v jedru poglavja.
S funkcijo select()
izberemo podmnožico stolpcev. Izberimo stolpce ime
, spol
in visina
:
# Osnovni R:
df[ , c("ime", "spol", "visina")]
## ime spol visina
## 1 Maja z 170
## 2 Ales m 180
## 3 Tom m 192
## 4 Barbara z 168
## 5 Simon m 177
## 6 Tina z 182
# dplyr:
select(df, ime, spol, visina)
## ime spol visina
## 1 Maja z 170
## 2 Ales m 180
## 3 Tom m 192
## 4 Barbara z 168
## 5 Simon m 177
## 6 Tina z 182
Opazimo, da nam pri uporabi dplyr stolpcev ni potrebno pisati v narekovajih. Tukaj gre za t. i. urejeno izbiranje (ang. tidy selection). Več o tem v jedru poglavja.
S funkcijo mutate()
dodajamo stolpce. Dodajmo višino v metrih:
# Osnovni R:
df2 <- df
df2$visina_v_metrih <- df2$visina / 100
df2
## ime spol starost visina visina_v_metrih
## 1 Maja z 23 170 1.70
## 2 Ales m 54 180 1.80
## 3 Tom m 21 192 1.92
## 4 Barbara z 35 168 1.68
## 5 Simon m 53 177 1.77
## 6 Tina z 21 182 1.82
# dplyr:
mutate(df, visina_v_metrih = visina / 100)
## ime spol starost visina visina_v_metrih
## 1 Maja z 23 170 1.70
## 2 Ales m 54 180 1.80
## 3 Tom m 21 192 1.92
## 4 Barbara z 35 168 1.68
## 5 Simon m 53 177 1.77
## 6 Tina z 21 182 1.82
S funkcijo arrange()
urejamo razpredelnico. Uredimo osebe po starosti:
# Osnovni R:
df[order(df$starost), ]
## ime spol starost visina
## 3 Tom m 21 192
## 6 Tina z 21 182
## 1 Maja z 23 170
## 4 Barbara z 35 168
## 5 Simon m 53 177
## 2 Ales m 54 180
# dplyr:
arrange(df, starost)
## ime spol starost visina
## 1 Tom m 21 192
## 2 Tina z 21 182
## 3 Maja z 23 170
## 4 Barbara z 35 168
## 5 Simon m 53 177
## 6 Ales m 54 180
S funkcijo summarise()
povzamemo podatke. Običajno se uporablja v kombinaciji z group_by()
. Izračunajmo povprečno višino glede na spol:
# Osnovni R:
aggregate(visina ~ spol, data = df, FUN = mean)
## spol visina
## 1 m 183.0000
## 2 z 173.3333
# dplyr:
summarise(group_by(df, spol), povp_visina = mean(visina))
## # A tibble: 2 × 2
## spol povp_visina
## <chr> <dbl>
## 1 m 183
## 2 z 173.
Naloga: Poglejmo si nov primer podatkov.
df <- data.frame(
podjetje = c("A", "B", "C", "D", "E"),
panoga = c("proizvodnja", "gostinstvo", "proizvodnja", "gostinstvo", "proizvodnja"),
st_zaposlenih = c(100, 20, 110, 15, 20),
dobicek = c(100000, 10000, 12000, 1000, 0)
)
Z uporabo dplyr:
- Izberite vrstice, ki imajo med (vključno) 10000 in 20000 dobička.
## podjetje panoga st_zaposlenih dobicek
## 1 B gostinstvo 20 10000
## 2 C proizvodnja 110 12000
- Izberite drugi in četrti stolpec.
## panoga dobicek
## 1 proizvodnja 100000
## 2 gostinstvo 10000
## 3 proizvodnja 12000
## 4 gostinstvo 1000
## 5 proizvodnja 0
- Dodajte stolpec, ki bo prikazal dobiček na zaposlenega.
## podjetje panoga st_zaposlenih dobicek dobicek_na_zaposlenega
## 1 A proizvodnja 100 100000 1000.00000
## 2 B gostinstvo 20 10000 500.00000
## 3 C proizvodnja 110 12000 109.09091
## 4 D gostinstvo 15 1000 66.66667
## 5 E proizvodnja 20 0 0.00000
- Uredite podjetja po številu zaposlenih.
## podjetje panoga st_zaposlenih dobicek
## 1 D gostinstvo 15 1000
## 2 B gostinstvo 20 10000
## 3 E proizvodnja 20 0
## 4 A proizvodnja 100 100000
## 5 C proizvodnja 110 12000
- Poiščite maksimalno število zaposlenih glede na panogo.
## # A tibble: 2 × 2
## panoga max_st_zaposlenih
## <chr> <dbl>
## 1 gostinstvo 20
## 2 proizvodnja 110
1.2 Sodobna razpredelnica: tibble
Najprej si poglejmo podatke, na katerih se bomo naučili osnovnih konceptov slovnice ravnanja s podatki. V mapi data-raw se nahajajo podatki DS-jobs.csv. Gre za rezultate ankete, ki so jo v povezavi z industrijo izvedli na spletni strani Kaggle (https://www.kaggle.com/kaggle/kaggle-survey-2017) leta 2017 z namenom raziskati trg dela na področju podatkovnih ved in strojnega učenja. Podatki so shranjeni v tekstovni datoteki, kjer so elementi ločeni s podpičjem. Preberimo podatke v našo sejo R:
ds_jobs <- read.csv2("./data-raw/DS-jobs.csv")
head(ds_jobs)
## Gender Country Age EmploymentStatus
## 1 Female Australia 43 Employed full-time
## 2 Male Russia 33 Employed full-time
## 3 Male Taiwan 26 Employed full-time
## 4 Male United States 25 Employed part-time
## 5 Male United States 33 Employed full-time
## 6 Male Czech Republic 21 Employed part-time
## CurrentJobTitle LanguageRecommendation
## 1 Business Analyst Python
## 2 Software Developer/Software Engineer Python
## 3 Software Developer/Software Engineer Python
## 4 Researcher Python
## 5 Scientist/Researcher Matlab
## 6 Other Python
## FormalEducation
## 1 Bachelor's degree
## 2 Bachelor's degree
## 3 Master's degree
## 4 Bachelor's degree
## 5 Doctoral degree
## 6 Some college/university study without earning a bachelor's degree
## Major CompensationAmount CompensationCurrency
## 1 80000 AUD
## 2 Other 1200000 RUB
## 3 Computer Science 1100000 TWD
## 4 Physics 20000 USD
## 5 Electrical Engineering 100000 USD
## 6 Computer Science 20000 CZK
## TimeGatheringData TimeModelBuilding TimeProduction TimeVisualizing
## 1 60 10 5 15
## 2 40 30 15 10
## 3 35 20 25 10
## 4 0 80 0 20
## 5 0 0 0 0
## 6 20 60 20 0
## TimeFindingInsights TimeOtherSelect ExchangeRate
## 1 10 0 0.802310
## 2 5 0 0.017402
## 3 10 0 0.033304
## 4 0 0 1.000000
## 5 0 0 1.000000
## 6 0 0 0.045820
Spremenljivka ds_jobs
je tipa data.frame
. To je osnovna oblika, v kateri v R hranimo razpredelnice. V tidyverse obstaja paket tibble, ki je namenjen sodobni predstavitvi razpredelnice. Glavna funkcionalnost tega paketa je objekt tibble
, ki predstavlja nadgradnjo data frame. V preostanku knjige bomo za objekte data.frame
uporabljali izraz "data frame" in za objekte tipa tibble
izraz "tibble". Večina funkcij v tidyverse sicer lahko kot vhodni podatek prejme data frame, ampak ga nekatere potem samodejno pretvorijo v tibble. Kot dobro prakso predlagamo delo izključno s tibble. Poleg kompatibilnosti s funkcijami tidyverse je še nekaj drugih razlik v primerjavi z data frame, večino le-teh bomo spoznali v preostanku knjige.
Pretvorimo sedaj ta data frame v tibble s funkcijo as_tibble()
.
library(tidyverse)
ds_jobs <- as_tibble(ds_jobs)
ds_jobs
## # A tibble: 4,523 × 17
## Gender Country Age EmploymentStatus CurrentJobTitle LanguageRecomme…
## <chr> <chr> <int> <chr> <chr> <chr>
## 1 Female Australia 43 Employed full-t… Business Analy… Python
## 2 Male Russia 33 Employed full-t… Software Devel… Python
## 3 Male Taiwan 26 Employed full-t… Software Devel… Python
## 4 Male United States 25 Employed part-t… Researcher Python
## 5 Male United States 33 Employed full-t… Scientist/Rese… Matlab
## 6 Male Czech Republic 21 Employed part-t… Other Python
## 7 Male Russia 22 Employed full-t… Data Analyst Python
## 8 Male Netherlands 51 Employed full-t… Engineer R
## 9 Male Colombia 34 Employed full-t… Data Scientist Python
## 10 Male Germany 41 Independent con… Data Scientist Python
## # … with 4,513 more rows, and 11 more variables: FormalEducation <chr>,
## # Major <chr>, CompensationAmount <dbl>, CompensationCurrency <chr>,
## # TimeGatheringData <int>, TimeModelBuilding <dbl>, TimeProduction <dbl>,
## # TimeVisualizing <dbl>, TimeFindingInsights <dbl>, TimeOtherSelect <int>,
## # ExchangeRate <dbl>
Opazimo, da je oblika prikaza podatkov sedaj nekoliko drugačna. Najbolj očitna razlika je, da imamo na zaslonu prikazanih samo toliko stolpcev, kot jih je možno prikazati na zaslonu. Preostali stolpci so samo zapisani zaporedno z imeni, da lahko vidimo, katere stolpce še imamo v podatkih. S tem preprečimo, da bi izpis postal nepregleden. Še vedno lahko vidimo vse oziroma več stolpcev z uporabo View()
ali pa če tibble izpišemo s pomočjo print()
in ustrezno nastavitvijo širine, na primer print(ds_jobs, width = 120)
. Izpis tibble pa nam nudi še nekaj dodatnih informacij v primerjavi z data frame. V prvi vrstici imamo izpisano dimenzijo podatkov -- število vrstic in število stolpcev. Pod vsako spremenljivko je zapisan tudi njen tip. Tibble tudi dopušča imena stolpcev, ki niso standardna za R (na primer vsebujejo -
in podobno), čeprav uporaba takih imen ni dobra praksa. Več o tem bomo povedali kasneje.
1.3 Urejeno ovrednotenje
Preden začnemo resneje delati z glagoli slovnice ravnanja s podatki, spoznajmo t. i. urejeno ovrednotenje (ang. tidy evaluation). To je posebnost tidyverse in večina glagolov v dplyr ga uporablja. Kaj pa je urejeno ovrednotenje? To je nestandarden pristop k ovrednotenju izrazov v programskem jeziku R. V pripravi smo že srečali dva primera:
- Pri funkciji
filter()
ni bilo potrebno vsakič navestidf$
za izbiro spremenljivk iz razpredelnice. - Pri funkciji
select()
nismo potrebovali narekovajev.
Oba sta primera dveh vrst urejenega ovrednotenja:
- Pri nekaterih glagolih v dplyr lahko uporabimo spremenljivke (stolpce) tibbla (ali razpredelnice), kot da bi bile spremenljivke v globalnem okolju (torej lahko uporabimo
moja_spremenljivka
namestodf$moja_spremenljivka
). Temu pravimo maskiranje podatkov (ang. data masking). Funkcije, ki podpirajo to strukturo in jih bomo spoznali v nadaljevanju so:arrange()
,count()
,filter()
,group_by()
,mutate()
insummarise()
. - Pri nekaterih glagolih v dplyr lahko na lažji način izberemo spremenljivke (stolpce) glede na njihovo pozicijo, ime ali tip (na primer izbira stolpcev po imenu brez narekovajev, izbira stolpcev ki se začnejo na določen niz, izbira samo številskih stolpcev). Temu pravimo urejeno izbiranje (ang. tidy selection). Funkcije, ki podpirajo to strukturo so:
across()
,count()
,rename()
,select()
inpull()
.
Informacije o tem, ali funkcija vsebuje maskiranje podatkov ali urejeno izbiranje, lahko najdemo v datoteki s pomočjo pod razdelkom Arguments.
1.4 Izbira vrstic s filter()
S funkcijo filter()
izbiramo podmnožico vrstic glede na izbrane pogoje. Sintaksa je:
filter(<tibble>, <pogoj1>, <pogoj2>, ...)
Kot prvi argument podamo tibble s podatki, potem pa z vejicami ločene pogoje. Izberimo vse osebe mlajše od 30 let:
library(dplyr)
filter(ds_jobs, Age < 30)
## # A tibble: 1,729 × 17
## Gender Country Age EmploymentStatus CurrentJobTitle LanguageRecomme…
## <chr> <chr> <int> <chr> <chr> <chr>
## 1 Male Taiwan 26 Employed full-t… Software Devel… Python
## 2 Male United States 25 Employed part-t… Researcher Python
## 3 Male Czech Republic 21 Employed part-t… Other Python
## 4 Male Russia 22 Employed full-t… Data Analyst Python
## 5 Male Poland 29 Employed full-t… Software Devel… Python
## 6 Male Other 28 Employed full-t… Data Scientist R
## 7 Male Mexico 26 Employed part-t… Data Scientist Python
## 8 Male Singapore 24 Employed full-t… Data Analyst Python
## 9 Male India 29 Employed full-t… Data Scientist R
## 10 Male United States 25 Employed full-t… Engineer Python
## # … with 1,719 more rows, and 11 more variables: FormalEducation <chr>,
## # Major <chr>, CompensationAmount <dbl>, CompensationCurrency <chr>,
## # TimeGatheringData <int>, TimeModelBuilding <dbl>, TimeProduction <dbl>,
## # TimeVisualizing <dbl>, TimeFindingInsights <dbl>, TimeOtherSelect <int>,
## # ExchangeRate <dbl>
Več pogojev ločimo z vejico, kadar želimo, da veljajo vsi pogoji (enakovredno uporabi operatorja in -- &
pri naštevanju pogojev). Poglejmo si vse osebe mlajše od 30 let, ki prihajajo iz Nemčije:
filter(ds_jobs, Age < 30, Country == "Germany")
## # A tibble: 42 × 17
## Gender Country Age EmploymentStatus CurrentJobTitle LanguageRecomme…
## <chr> <chr> <int> <chr> <chr> <chr>
## 1 Female Germany 24 Employed part-time Scientist/Resear… R
## 2 Male Germany 28 Employed full-time Scientist/Resear… Python
## 3 Male Germany 24 Independent contract… Data Scientist Python
## 4 Female Germany 29 Employed full-time Business Analyst SQL
## 5 Male Germany 26 Employed part-time Researcher Python
## 6 Male Germany 27 Employed full-time Data Scientist Python
## 7 Female Germany 26 Employed part-time Statistician R
## 8 Male Germany 26 Independent contract… Data Scientist Python
## 9 Male Germany 29 Employed full-time Machine Learning… Python
## 10 Male Germany 25 Employed full-time Data Scientist Python
## # … with 32 more rows, and 11 more variables: FormalEducation <chr>,
## # Major <chr>, CompensationAmount <dbl>, CompensationCurrency <chr>,
## # TimeGatheringData <int>, TimeModelBuilding <dbl>, TimeProduction <dbl>,
## # TimeVisualizing <dbl>, TimeFindingInsights <dbl>, TimeOtherSelect <int>,
## # ExchangeRate <dbl>
V kolikor želimo, da velja vsaj eden izmed pogojev, moramo uporabiti operator ali -- |
. Poglejmo si vse osebe mlajše od 30 ali starejše od 50 let:
filter(ds_jobs, Age < 30 | Age > 50)
## # A tibble: 2,006 × 17
## Gender Country Age EmploymentStatus CurrentJobTitle LanguageRecomme…
## <chr> <chr> <int> <chr> <chr> <chr>
## 1 Male Taiwan 26 Employed full-t… Software Devel… Python
## 2 Male United States 25 Employed part-t… Researcher Python
## 3 Male Czech Republic 21 Employed part-t… Other Python
## 4 Male Russia 22 Employed full-t… Data Analyst Python
## 5 Male Netherlands 51 Employed full-t… Engineer R
## 6 Male Poland 29 Employed full-t… Software Devel… Python
## 7 Male Other 28 Employed full-t… Data Scientist R
## 8 Male Mexico 26 Employed part-t… Data Scientist Python
## 9 Male Singapore 24 Employed full-t… Data Analyst Python
## 10 Male India 29 Employed full-t… Data Scientist R
## # … with 1,996 more rows, and 11 more variables: FormalEducation <chr>,
## # Major <chr>, CompensationAmount <dbl>, CompensationCurrency <chr>,
## # TimeGatheringData <int>, TimeModelBuilding <dbl>, TimeProduction <dbl>,
## # TimeVisualizing <dbl>, TimeFindingInsights <dbl>, TimeOtherSelect <int>,
## # ExchangeRate <dbl>
Če želimo nek kategorični stolpec pogojiti z večimi vrednostmi (na primer udeležence iz večih držav), lahko namesto večih |
uporabimo operator %in%
, ki preveri, če je element del množice:
filter(ds_jobs, Country %in% c("Germany", "Canada", "Ireland"))
## # A tibble: 306 × 17
## Gender Country Age EmploymentStatus CurrentJobTitle LanguageRecomme…
## <chr> <chr> <int> <chr> <chr> <chr>
## 1 Male Germany 41 Independent contrac… Data Scientist Python
## 2 Female Germany 49 Employed part-time Scientist/Resea… Python
## 3 Male Germany 44 Employed full-time Other Python
## 4 A diffe… Canada 23 Employed full-time Scientist/Resea… Python
## 5 Female Germany 24 Employed part-time Scientist/Resea… R
## 6 Male Canada 52 Employed full-time Software Develo… Python
## 7 Male Ireland 27 Employed full-time Data Scientist Python
## 8 Male Canada 24 Employed full-time Business Analyst Python
## 9 Male Canada 46 Employed full-time Data Scientist Python
## 10 Male Canada 31 Employed full-time Data Analyst R
## # … with 296 more rows, and 11 more variables: FormalEducation <chr>,
## # Major <chr>, CompensationAmount <dbl>, CompensationCurrency <chr>,
## # TimeGatheringData <int>, TimeModelBuilding <dbl>, TimeProduction <dbl>,
## # TimeVisualizing <dbl>, TimeFindingInsights <dbl>, TimeOtherSelect <int>,
## # ExchangeRate <dbl>
1.4.1 Manjkajoče vrednosti
Vrstice pogosto filtriramo na podlagi manjkajočih vrednosti. Včasih so te pomembne za samo analizo, saj nas lahko zanimajo razlogi za njihov pojav. Včasih pa so to nepomembne vrstice, saj nam ne prinesejo dodatne informacije. V tem primeru jih običajno kar izločimo iz nadaljnje analize.
V nadaljevanju bomo spoznali, kako dodati nov stolpec, in to ilustrirali na izračunu plače v dolarjih. Za to bomo potrebovali stolpca CompensationAmount
in ExchangeRate
. V slednjem je kar nekaj manjkajočih vrednosti. Takšne vrstice bodo za analizo plač neuporabne, zato jih bomo sedaj izločili iz podatkov. Ali je vrednost enaka NA
(objekt, ki predstavlja manjkajočo vrednost v R) preverimo s funkcijo is.na()
. Izločimo sedaj te vrstice:
ds_jobs <- filter(ds_jobs, !is.na(ExchangeRate))
Podobno kot v zgornjem primeru lahko v pogoju nastopa poljubna funkcija.
1.5 Izbira stolpcev s select()
S funkcijo select()
izbiramo podmnožico stolpcev. Osnovna sintaksa je:
select(<tibble>, <stolpec1>, <stolpec2>, ...)
Izberimo sedaj stolpce Country
, Age
in EmploymentStatus
.
select(ds_jobs, Country, Age, EmploymentStatus)
## # A tibble: 3,781 × 3
## Country Age EmploymentStatus
## <chr> <int> <chr>
## 1 Australia 43 Employed full-time
## 2 Russia 33 Employed full-time
## 3 Taiwan 26 Employed full-time
## 4 United States 25 Employed part-time
## 5 United States 33 Employed full-time
## 6 Czech Republic 21 Employed part-time
## 7 Russia 22 Employed full-time
## 8 Colombia 34 Employed full-time
## 9 Germany 41 Independent contractor, freelancer, or self-employed
## 10 Poland 29 Employed full-time
## # … with 3,771 more rows
Izberimo vse stolpce razen teh treh stolpcev. Za to enostavno dodamo minus pred imenom stolpca, ki ga želimo izločiti:
select(ds_jobs, -Country, -Age, -EmploymentStatus)
## # A tibble: 3,781 × 14
## Gender CurrentJobTitle LanguageRecommen… FormalEducation Major
## <chr> <chr> <chr> <chr> <chr>
## 1 Female Business Analyst Python Bachelor's degree ""
## 2 Male Software Develope… Python Bachelor's degree "Other"
## 3 Male Software Develope… Python Master's degree "Computer …
## 4 Male Researcher Python Bachelor's degree "Physics"
## 5 Male Scientist/Researc… Matlab Doctoral degree "Electrica…
## 6 Male Other Python Some college/univers… "Computer …
## 7 Male Data Analyst Python Bachelor's degree "Informati…
## 8 Male Data Scientist Python Master's degree "Computer …
## 9 Male Data Scientist Python I did not complete a… ""
## 10 Male Software Develope… Python Master's degree "Computer …
## # … with 3,771 more rows, and 9 more variables: CompensationAmount <dbl>,
## # CompensationCurrency <chr>, TimeGatheringData <int>,
## # TimeModelBuilding <dbl>, TimeProduction <dbl>, TimeVisualizing <dbl>,
## # TimeFindingInsights <dbl>, TimeOtherSelect <int>, ExchangeRate <dbl>
Izberimo vse stolpce med Country
in Major
. Podobno kot v R 1:10
našteje vsa cela števila med 1 in 10, operator :
v tidyverse izbere vse stolpce med Country
in Major
:
select(ds_jobs, Country:Major)
## # A tibble: 3,781 × 7
## Country Age EmploymentStatus CurrentJobTitle LanguageRecomme…
## <chr> <int> <chr> <chr> <chr>
## 1 Australia 43 Employed full-time Business Analyst Python
## 2 Russia 33 Employed full-time Software Develope… Python
## 3 Taiwan 26 Employed full-time Software Develope… Python
## 4 United States 25 Employed part-time Researcher Python
## 5 United States 33 Employed full-time Scientist/Researc… Matlab
## 6 Czech Republic 21 Employed part-time Other Python
## 7 Russia 22 Employed full-time Data Analyst Python
## 8 Colombia 34 Employed full-time Data Scientist Python
## 9 Germany 41 Independent contrac… Data Scientist Python
## 10 Poland 29 Employed full-time Software Develope… Python
## # … with 3,771 more rows, and 2 more variables: FormalEducation <chr>,
## # Major <chr>
Izberimo vse stolpce, ki se začnejo z besedo Time
. Za to bomo uporabili funkcijo starts_with()
. Ta funkcija je t. i. selection helper, kar pomeni, da jo lahko uporabimo le znotraj funkcij, ki omogočajo urejeno izbiro in nam omogoča lažjo izbiro na podlagi nekega pogoja. V tem primeru je ta pogoj, da se beseda začne na določen niz:
select(ds_jobs, starts_with("Time"))
## # A tibble: 3,781 × 6
## TimeGatheringData TimeModelBuilding TimeProduction TimeVisualizing
## <int> <dbl> <dbl> <dbl>
## 1 60 10 5 15
## 2 40 30 15 10
## 3 35 20 25 10
## 4 0 80 0 20
## 5 0 0 0 0
## 6 20 60 20 0
## 7 50 20 10 5
## 8 60 10 20 5
## 9 50 10 20 10
## 10 25 20 25 20
## # … with 3,771 more rows, and 2 more variables: TimeFindingInsights <dbl>,
## # TimeOtherSelect <int>
Poleg starts_with()
dplyr vsebuje še več takšnih funkcij:
ends_with()
Ali se ime stolpca konča na določen niz?contains()
Ali ime stolpca vsebuje niz?matches()
Ali ime stolpca ustreza regularnemu izrazu? Več o regularnih izrazih bomo povedali v 3. predavanju.num_range()
Ali ime stolpca vsebuje števila znotraj množice števil? Na primer, če imamo stolpce, ki v imenu vsebujejo števila -- stolpec1, stolpec2, in tako naprej.
1.6 Urejanje vrstic z arrange()
Vrstice lahko tudi uredimo glede na vrednosti v posameznih stolpcih. Za to uporabimo funkcijo arrange()
. Sintaksa te funkcije je:
arrange(<tibble>, <stolpec1>, <stolpec2>, ...)
kjer stolpci predstavljajo vrednosti, po katerih želimo urediti tibble.
Ustvarimo najprej nov tibble, v katerem bomo izbrali podmnožico stolpcev.
ds_jobs_tmp <- select(ds_jobs, CurrentJobTitle, Country,
CompensationCurrency, Age, CompensationAmount)
Uredimo sedaj podatke glede na leta:
arrange(ds_jobs_tmp, Age)
## # A tibble: 3,781 × 5
## CurrentJobTitle Country CompensationCurre… Age CompensationAmo…
## <chr> <chr> <chr> <int> <dbl>
## 1 Predictive Modeler Australia AUD 0 78000
## 2 Scientist/Researcher United St… USD 1 100000
## 3 Programmer Other GBP 11 0
## 4 Data Scientist United St… USD 16 50000
## 5 Software Developer/Soft… Russia USD 18 40000
## 6 Programmer Other USD 18 1000
## 7 Machine Learning Engine… Other USD 19 30000
## 8 Programmer Russia USD 19 40000
## 9 Scientist/Researcher Canada CAD 19 0
## 10 Computer Scientist Brazil BRL 19 400
## # … with 3,771 more rows
Opazimo, da imamo nekaj neveljavnih starosti, na primer 0 in 1, najverjetneje tudi 11. Prav tako imamo nekaj nesmiselnih vrednosti v stolpcu o plači. Pri celostni analizi bi seveda raziskali, zakaj je prišlo do takih vrednosti, oziroma bi jih izločili iz analize. Za namen spoznavanja ravnanja s podatki in dplyr to ni pomembno, tako da temu ne bomo posvečali pozornosti. Bralcem pa predlagamo, naj razmislijo, kako bi se tega lotili z že naučenimi koncepti.
Če želimo podatke urediti padajoče, potem uporabimo funkcijo desc()
:
arrange(ds_jobs_tmp, desc(Age))
## # A tibble: 3,781 × 5
## CurrentJobTitle Country CompensationCurre… Age CompensationAmo…
## <chr> <chr> <chr> <int> <dbl>
## 1 Statistician United Ki… ILS 100 100000000000
## 2 Other Other EUR 99 15000
## 3 Researcher Portugal EUR 78 63000
## 4 Data Scientist Canada USD 75 110
## 5 Software Developer/Soft… Netherlan… EUR 73 40000
## 6 Data Analyst Russia USD 70 14000
## 7 Business Analyst United St… USD 70 130000
## 8 Machine Learning Engine… United Ki… GBP 70 40000
## 9 Scientist/Researcher United St… USD 69 200000
## 10 Business Analyst United St… USD 68 125000
## # … with 3,771 more rows
Uredimo lahko tudi glede na več stolpcev, kjer se najprej uredi po prvem zapisanem, nato drugem, itd.:
arrange(ds_jobs_tmp, Age, CompensationAmount)
## # A tibble: 3,781 × 5
## CurrentJobTitle Country CompensationCurre… Age CompensationAmo…
## <chr> <chr> <chr> <int> <dbl>
## 1 Predictive Modeler Australia AUD 0 78000
## 2 Scientist/Researcher United St… USD 1 100000
## 3 Programmer Other GBP 11 0
## 4 Data Scientist United St… USD 16 50000
## 5 Programmer Other USD 18 1000
## 6 Software Developer/Soft… Russia USD 18 40000
## 7 Scientist/Researcher Canada CAD 19 0
## 8 Computer Scientist Brazil BRL 19 400
## 9 Machine Learning Engine… Other USD 19 30000
## 10 Programmer Russia USD 19 40000
## # … with 3,771 more rows
1.7 Dodajanje novih spremenljivk z mutate()
Pogosto želimo ustvariti nove stolpce, ki so izpeljani iz obstoječih stolpcev. Pri naših podatkih imamo stolpec CompensationAmount
, ki predstavlja letno plačo in ExchangeRate
, ki predstavlja menjalni tečaj lokalne valute v ameriški dolar. Če želimo imeti primerljive podatke, moramo izračunati vrednosti v dolarjih za vse podatke. Za to uporabimo funkcijo mutate()
, ki doda stolpec (ali več stolpcev). Sintaksa funkcije je:
<tibble> <- mutate(<tibble>, <ime-novega-stolpca> = <funkcija-obstoječih-stolpcev>, ...)
Dodajmo stolpec CompensationUSD
, ki bo prikazal letno plačo v USD:
ds_jobs <- mutate(ds_jobs, CompensationUSD = CompensationAmount * ExchangeRate)
select(ds_jobs, CompensationAmount, ExchangeRate, CompensationUSD)
## # A tibble: 3,781 × 3
## CompensationAmount ExchangeRate CompensationUSD
## <dbl> <dbl> <dbl>
## 1 80000 0.802 64185.
## 2 1200000 0.0174 20882.
## 3 1100000 0.0333 36634.
## 4 20000 1 20000
## 5 100000 1 100000
## 6 20000 0.0458 916.
## 7 624000 0.0174 10859.
## 8 156000000 0.000342 53352
## 9 150000 1.20 179374.
## 10 126000 0.281 35419.
## # … with 3,771 more rows
Znotraj klica mutate()
lahko uporabimo stolpce, ki smo jih ustvarili v istem klicu v preteklih vrsticah. Recimo, da želimo poleg plače v USD izračunati še mesečno plačo v USD:
ds_jobs <- mutate(ds_jobs,
CompensationUSD = CompensationAmount * ExchangeRate,
MonthlyCompUSD = CompensationUSD / 12)
select(ds_jobs, CompensationAmount, ExchangeRate, CompensationUSD, MonthlyCompUSD)
## # A tibble: 3,781 × 4
## CompensationAmount ExchangeRate CompensationUSD MonthlyCompUSD
## <dbl> <dbl> <dbl> <dbl>
## 1 80000 0.802 64185. 5349.
## 2 1200000 0.0174 20882. 1740.
## 3 1100000 0.0333 36634. 3053.
## 4 20000 1 20000 1667.
## 5 100000 1 100000 8333.
## 6 20000 0.0458 916. 76.4
## 7 624000 0.0174 10859. 905.
## 8 156000000 0.000342 53352 4446
## 9 150000 1.20 179374. 14948.
## 10 126000 0.281 35419. 2952.
## # … with 3,771 more rows
1.8 Povzemanje vrednosti s summarise()
Funkcija summarise()
se uporablja za povzemanje vrednosti (na primer povprečja, vsote, števci, ...). Sintaksa funkcije je:
summarise(<tibble>, <ime-povzetka> = <funkcija-ki-povzame-stolpec>, ...)
Najprej poglejmo delovanje te funkcije, tako da povzamemo povprečen čas priprave podatkov:
summarise(ds_jobs, MeanDataCleaning = mean(TimeGatheringData))
## # A tibble: 1 × 1
## MeanDataCleaning
## <dbl>
## 1 37.3
Funkcija enostavno vrne povprečje stolpca TimeGatheringData
. Ta informacija je sicer uporabna, ampak to ni edina funkcionalnost te funkcije in je običajno ne uporabljamo v tej obliki. Njena moč se izrazi, ko jo uporabimo v kombinaciji z ukazom group_by()
. Ta ukaz združi vrstice glede na vrednosti v podanih stolpcih. Združene vrednosti imajo posebno funkcijo v paketu dplyr in vplivajo na funkcionalnosti funkcij summarise()
, mutate()
in filter()
. Vpliv grupiranja na mutate()
in filter()
si bomo ogledali nekoliko kasneje, poglejmo sedaj vpliv na summarise()
. Recimo, da nas zanima, v katerih službah je potrebnega največ čiščenja podatkov. Najprej podatke združimo po stolpcu CurrentJobTitle
, potem pa uporabimo summarise()
:
ds_jobs_grouped <- group_by(ds_jobs, CurrentJobTitle)
summarise(ds_jobs_grouped, MeanDataCleaning = mean(TimeGatheringData))
## # A tibble: 17 × 2
## CurrentJobTitle MeanDataCleaning
## <chr> <dbl>
## 1 "" 40
## 2 "Business Analyst" 37.9
## 3 "Computer Scientist" 33.3
## 4 "Data Analyst" 41.2
## 5 "Data Miner" 48.0
## 6 "Data Scientist" 39.4
## 7 "DBA/Database Engineer" 37.7
## 8 "Engineer" 36.4
## 9 "Machine Learning Engineer" 34.7
## 10 "Operations Research Practitioner" 37.8
## 11 "Other" 36.3
## 12 "Predictive Modeler" 37.1
## 13 "Programmer" 35.8
## 14 "Researcher" 31.3
## 15 "Scientist/Researcher" 33.5
## 16 "Software Developer/Software Engineer" 36.9
## 17 "Statistician" 34.7
Izgleda, da so povprečja kar blizu -- čas čiščenja podatkov je relativno neodvisen od delovnega mesta.
Povzemamo lahko tudi preko večih stolpcev. Poglejmo si število ljudi z različnimi statusi zaposlitve v kombinaciji z izobrazbo. Da preštejemo število vrstic, ki ustrezajo grupiranju, uporabimo funkcijo n()
:
ds_jobs_grouped <- group_by(ds_jobs, FormalEducation, EmploymentStatus)
summarise(ds_jobs_grouped, Count = n())
## # A tibble: 21 × 3
## # Groups: FormalEducation [8]
## FormalEducation EmploymentStatus Count
## <chr> <chr> <int>
## 1 "" Employed full-time 1
## 2 "Bachelor's degree" Employed full-time 857
## 3 "Bachelor's degree" Employed part-time 52
## 4 "Bachelor's degree" Independent contractor, freelanc… 76
## 5 "Doctoral degree" Employed full-time 719
## 6 "Doctoral degree" Employed part-time 26
## 7 "Doctoral degree" Independent contractor, freelanc… 50
## 8 "I did not complete any formal educa… Employed full-time 13
## 9 "I did not complete any formal educa… Employed part-time 2
## 10 "I did not complete any formal educa… Independent contractor, freelanc… 10
## # … with 11 more rows
Ker je štetje primerov zelo pogosta operacija, obstaja tudi funkcija count()
, ki naredi enako kot kombinacija group_by()
in summarise()
:
count(ds_jobs, FormalEducation, EmploymentStatus)
## # A tibble: 21 × 3
## FormalEducation EmploymentStatus n
## <chr> <chr> <int>
## 1 "" Employed full-time 1
## 2 "Bachelor's degree" Employed full-time 857
## 3 "Bachelor's degree" Employed part-time 52
## 4 "Bachelor's degree" Independent contractor, freelanc… 76
## 5 "Doctoral degree" Employed full-time 719
## 6 "Doctoral degree" Employed part-time 26
## 7 "Doctoral degree" Independent contractor, freelanc… 50
## 8 "I did not complete any formal educa… Employed full-time 13
## 9 "I did not complete any formal educa… Employed part-time 2
## 10 "I did not complete any formal educa… Independent contractor, freelanc… 10
## # … with 11 more rows
1.9 Pipe
V praksi ravnanje s podatki zajame večino, če ne kar vseh funkcij, ki smo jih predstavili do sedaj. Če želimo sproti shranjevati naše spremembe, moramo po vsaki uporabi funkcije spremenjene podatke ponovno shraniti v spremenljivko. To lahko postane nekoliko nepregledno. Poglejmo si potek dela, kjer bomo nad osnovnimi podatki izvedli te operacije:
- Izbrali bomo vrstice, kjer so osebe starejše od 30 let in država ni
Other
ali prazen niz. - Izločili vse stolpce, ki vsebujejo niz
Time
. - Izračunali stolpec s plačo v ameriških dolarjih.
- Povzeli plačo glede na državo.
Z uporabo shranjevanja podatkov v spremenljivko, kot smo navajeni iz osnovne različice R, bi s funkcijami iz dplyr izgledalo takole:
ds_jobs2 <- read.csv2("./data-raw/DS-jobs.csv")
ds_jobs2 <- as_tibble(ds_jobs2)
ds_jobs2 <- filter(ds_jobs2, Age > 30, !(Country %in% c("Other", "")))
ds_jobs2 <- select(ds_jobs2, -contains("Time"))
ds_jobs2 <- mutate(ds_jobs2, CompensationUSD = CompensationAmount * ExchangeRate)
ds_jobs2 <- group_by(ds_jobs2, Country)
ds_jobs2_summarised <- summarise(ds_jobs2, MeanCompensation = mean(CompensationUSD, na.rm = T))
ds_jobs2_summarised
## # A tibble: 51 × 2
## Country MeanCompensation
## <chr> <dbl>
## 1 Argentina 39282.
## 2 Australia 112800.
## 3 Belarus 33500
## 4 Belgium 74141.
## 5 Brazil 47799.
## 6 Canada 85471.
## 7 Chile 44152.
## 8 Colombia 43303.
## 9 Czech Republic 50223.
## 10 Denmark 88136.
## # … with 41 more rows
Pri računanju povprečja smo uporabili argument na.rm = T
, s katerim smo manjkajoče vrednosti ignorirali. Celoten postopek je vseboval kar nekaj prepisovanja. Predvsem spremenljivko ds_jobs2
smo morali prepisati kar 6-krat. Dplyr pa vsebuje poseben operator, ki ga imenujemo pipe in ga označimo z %>%
. S tem operatorjem funkcije povežemo v sosledje. Poglejmo si, kako deluje:
ds_jobs2 <- read.csv2("./data-raw/DS-jobs.csv")
ds_jobs2_summarised <- ds_jobs2 %>%
filter(Age > 30, !(Country %in% c("Other", ""))) %>%
select(-contains("Time")) %>%
mutate(CompensationUSD = CompensationAmount * ExchangeRate) %>%
group_by(Country) %>%
summarise(MeanCompensation = mean(CompensationUSD, na.rm = T))
ds_jobs2_summarised
## # A tibble: 51 × 2
## Country MeanCompensation
## <chr> <dbl>
## 1 Argentina 39282.
## 2 Australia 112800.
## 3 Belarus 33500
## 4 Belgium 74141.
## 5 Brazil 47799.
## 6 Canada 85471.
## 7 Chile 44152.
## 8 Colombia 43303.
## 9 Czech Republic 50223.
## 10 Denmark 88136.
## # … with 41 more rows
Sedaj smo do povzetka prišli z zaporednim izvajanjem operacij nad spremenljivko ds_jobs
. Ta način je bolj pregleden, saj bralec kode takoj opazi, da se je vse izvajalo nad istimi podatki. Opazimo tudi, zakaj gre za slovnico ravnanja s podatki. Programska koda zapisana zgoraj se bere skoraj kot naravni jezik. Na primer, izberi vrstice, kjer so leta večja od 30 in država ni v ustrezni množici. Zatem izberi stolpce, ki ne vsebujejo besede Time. Dodaj novo spremenljivko, združi podatke in jih povzemi.
1.10 filter()
in mutate()
na združenih podatkih
Spoznali smo, kako funkcija group_by()
vpliva na povzemanje podatkov. Uporabimo pa jo lahko tudi v povezavi s filter()
in mutate()
. Kombinacija z izbiro vrstic pride prav, kadar želimo pogojno izbiro na nek drugi stolpec. Kot primer si poglejmo, kako bi iz podatkov za vsako državo filtrirali top 3 anketirance, ki prejmejo najvišjo plačo. Najprej bomo podatke grupirali, nato pa uporabili filter:
ds_jobs %>%
select(Country, Age, CurrentJobTitle, CompensationUSD) %>%
group_by(Country) %>%
filter(rank(desc(CompensationUSD)) <= 3) %>%
arrange(Country)
## # A tibble: 154 × 4
## # Groups: Country [53]
## Country Age CurrentJobTitle CompensationUSD
## <chr> <int> <chr> <dbl>
## 1 "" NA Data Scientist 107624.
## 2 "" 63 Machine Learning Engineer 160000
## 3 "" NA Operations Research Practitioner 120000
## 4 "Argentina" 55 Data Scientist 100000
## 5 "Argentina" 26 Data Scientist 65000
## 6 "Argentina" 26 Data Scientist 80000
## 7 "Australia" 39 Data Scientist 280808.
## 8 "Australia" 50 Data Miner 248716.
## 9 "Australia" 37 Software Developer/Software Engineer 400000
## 10 "Belarus" 22 Data Scientist 10800
## # … with 144 more rows
Kombinacija group_by()
in mutate()
je uporabna, kadar želimo ustvariti novo spremenljivko, pri kateri bomo pri izračunu potrebovali kak povzetek vrednosti znotraj posamezne skupine. Primer takšne transformacije je na primer standardiziranje znotraj skupine. Standardna ocena je:
\[ z_i = \frac{x_i - \bar{x}}{S_x}, \]
kjer je \(\bar{x}\) povprečje vektorja \(x\) in \(S_x\) njegov vzorčni standardni odklon.
Poskusimo za vsako državo izračunati vzorčno povprečno vrednost in standardni odklon, ter s tema vrednostima ustrezno transformirati plačo v USD. Da pa bo funkcija mutate()
vedela, katere vrednosti naj vzame za računanje teh dveh statistie moramo podatke najprej grupirati glede na državo:
ds_jobs %>%
select(Country, Age, CurrentJobTitle, CompensationUSD) %>%
group_by(Country) %>%
mutate(CompensationStand = (CompensationUSD - mean(CompensationUSD)) /
sd(CompensationUSD))
## # A tibble: 3,781 × 5
## # Groups: Country [53]
## Country Age CurrentJobTitle CompensationUSD CompensationSta…
## <chr> <int> <chr> <dbl> <dbl>
## 1 Australia 43 Business Analyst 64185. -0.617
## 2 Russia 33 Software Developer/Sof… 20882. -0.136
## 3 Taiwan 26 Software Developer/Sof… 36634. 0.0566
## 4 United States 25 Researcher 20000 -0.0468
## 5 United States 33 Scientist/Researcher 100000 -0.0347
## 6 Czech Republic 21 Other 916. -0.907
## 7 Russia 22 Data Analyst 10859. -0.417
## 8 Colombia 34 Data Scientist 53352 0.770
## 9 Germany 41 Data Scientist 179374. 2.35
## 10 Poland 29 Software Developer/Sof… 35419. 0.486
## # … with 3,771 more rows
Če ta tibble shranimo v novo spremenljivko, se bo informacija o združevanju ohranila.
ds_jobs_grouped <- ds_jobs %>%
select(Country, Age, CurrentJobTitle, CompensationUSD) %>%
group_by(Country, CurrentJobTitle)
ds_jobs_grouped
## # A tibble: 3,781 × 4
## # Groups: Country, CurrentJobTitle [543]
## Country Age CurrentJobTitle CompensationUSD
## <chr> <int> <chr> <dbl>
## 1 Australia 43 Business Analyst 64185.
## 2 Russia 33 Software Developer/Software Engineer 20882.
## 3 Taiwan 26 Software Developer/Software Engineer 36634.
## 4 United States 25 Researcher 20000
## 5 United States 33 Scientist/Researcher 100000
## 6 Czech Republic 21 Other 916.
## 7 Russia 22 Data Analyst 10859.
## 8 Colombia 34 Data Scientist 53352
## 9 Germany 41 Data Scientist 179374.
## 10 Poland 29 Software Developer/Software Engineer 35419.
## # … with 3,771 more rows
Opazimo, da ima ta tibble dodatno informacijo v drugi vrstici, ki nam sporoča, da je združen glede na spremenljivki Country
in CurrentJobTitle
. Poleg tega je v oglatih oklepajih zapisano število unikatnih skupin. Pri tem so vsi pari države in trenutne pozicije, za katere nimamo nobenega podatka, izpuščeni. Informacija o tem, da je ta tibble grupiran, je pomembna, saj se bodo vse nadaljnje operacije nad njim izvajale nad skupinami. Če tega ne želimo, lahko uporabimo funkcijo ungroup()
.
ds_jobs_ungrouped <- ds_jobs_grouped %>%
ungroup()
ds_jobs_ungrouped
## # A tibble: 3,781 × 4
## Country Age CurrentJobTitle CompensationUSD
## <chr> <int> <chr> <dbl>
## 1 Australia 43 Business Analyst 64185.
## 2 Russia 33 Software Developer/Software Engineer 20882.
## 3 Taiwan 26 Software Developer/Software Engineer 36634.
## 4 United States 25 Researcher 20000
## 5 United States 33 Scientist/Researcher 100000
## 6 Czech Republic 21 Other 916.
## 7 Russia 22 Data Analyst 10859.
## 8 Colombia 34 Data Scientist 53352
## 9 Germany 41 Data Scientist 179374.
## 10 Poland 29 Software Developer/Software Engineer 35419.
## # … with 3,771 more rows
1.11 Izvajanje operacij nad večimi stolpci z across()
S kombinacijo funkcij mutate()
in across()
lahko izvajamo isto operacijo hkrati na več stolpcih. Znotraj funkcije across()
lahko uporabljamo iste funkcije za izbiro kot znotraj select()
. Spremenimo vrednosti stolpcev, ki se začnejo s Time
, v deleže tako, da jih pomnožimo z 0.01. Na tem mestu bomo uporabili dva nova operatorja: .
in ~
. Operator .
v dplyr igra vlogo podatkov, nad katerimi operiramo. Operator ~
je nekakšna bližnjica, ki ustvari funkcijo. Na primer ~ x^2
je bližnjica za zapis function(x) {x^2}
. To je uporabno predvsem, ko funkcijo potrebujemo samo na enem mestu znotraj našega poteka dela in jo tako lahko na krajši način zapišemo. Poglejmo si sedaj spremembo stolpcev v deleže:
ds_jobs %>%
mutate(across(starts_with("Time"), ~ . * 0.01)) %>%
select(Country, CurrentJobTitle, starts_with("Time"))
## # A tibble: 3,781 × 8
## Country CurrentJobTitle TimeGatheringDa… TimeModelBuildi… TimeProduction
## <chr> <chr> <dbl> <dbl> <dbl>
## 1 Australia Business Analyst 0.6 0.1 0.05
## 2 Russia Software Develope… 0.4 0.3 0.15
## 3 Taiwan Software Develope… 0.35 0.2 0.25
## 4 United S… Researcher 0 0.8 0
## 5 United S… Scientist/Researc… 0 0 0
## 6 Czech Re… Other 0.2 0.6 0.2
## 7 Russia Data Analyst 0.5 0.2 0.1
## 8 Colombia Data Scientist 0.6 0.1 0.2
## 9 Germany Data Scientist 0.5 0.1 0.2
## 10 Poland Software Develope… 0.25 0.2 0.25
## # … with 3,771 more rows, and 3 more variables: TimeVisualizing <dbl>,
## # TimeFindingInsights <dbl>, TimeOtherSelect <dbl>
Funkciji across()
smo najprej podali stolpce, na katerih želimo izvajati izračune, nato pa funkcijo, ki jo želimo izvesti.
1.12 Povzemanje stolpcev
Pogosto želimo dobiti numerične povzetke glede na vrednosti v stolpcih. Z uporabo osnovne različice R to lahko naredimo s funkcijo apply()
, ki ji podamo tibble numeričnih vrednosti (lahko tudi data.frame
ali matriko), določimo dimenzijo 2, ki predstavlja stolpce, ter podamo kateri povzetek želimo (na primer povprečje, varianco, maksimalno vrednost, ...). Izračunajmo povprečja in standardne odklone stolpcev, ki se začnejo s Time
:
ds_jobs_times <- ds_jobs %>%
select(starts_with("Time"))
apply(ds_jobs_times, 2, mean, na.rm = T)
## TimeGatheringData TimeModelBuilding TimeProduction TimeVisualizing
## 37.341973 21.085472 11.172853 14.190924
## TimeFindingInsights TimeOtherSelect
## 13.375298 2.202176
apply(ds_jobs_times, 2, sd, na.rm = T)
## TimeGatheringData TimeModelBuilding TimeProduction TimeVisualizing
## 20.96041 15.19101 12.03243 10.99431
## TimeFindingInsights TimeOtherSelect
## 12.01139 11.18898
apply()
nam v teh primerih vrne vektor, čeprav smo operacijo izvajali na tibble. Ideja paketa tidyverse je, da so izhodni podatki enakega tipa kot vhodni -- v tem primeru tibble. Če želimo izračunati povzetke za vsak stolpec, lahko v paketu dplyr uporabimo kombinacijo funkcije summarise()
in across()
. Kot smo že spoznali, nam funkcija across()
omogoča izvajanje operacij nad večimi stolpci.
ds_jobs %>%
summarise(across(starts_with("Time"), mean, na.rm = T))
## # A tibble: 1 × 6
## TimeGatheringData TimeModelBuilding TimeProduction TimeVisualizing
## <dbl> <dbl> <dbl> <dbl>
## 1 37.3 21.1 11.2 14.2
## # … with 2 more variables: TimeFindingInsights <dbl>, TimeOtherSelect <dbl>
Povzetke lahko enostavno izračunamo tudi za različne skupine z uporabo funkcije group_by()
:
ds_jobs %>%
group_by(EmploymentStatus) %>%
summarise(across(starts_with("Time"), mean, na.rm = T))
## # A tibble: 3 × 7
## EmploymentStatus TimeGatheringDa… TimeModelBuildi… TimeProduction
## <chr> <dbl> <dbl> <dbl>
## 1 Employed full-time 37.6 20.6 11.0
## 2 Employed part-time 37.4 26.1 10.3
## 3 Independent contractor, free… 34.8 23.0 12.8
## # … with 3 more variables: TimeVisualizing <dbl>, TimeFindingInsights <dbl>,
## # TimeOtherSelect <dbl>
1.13 Povzemanje vrstic
Kadar analiziramo podatke, preverimo, ali so vnešeni podatki smiselni. Na primer, v stolpcih, ki se začnejo s Time
, so odstotkovne vrednosti časa, ki ga anketiranci porabijo za posamezne naloge. Te bi se morale sešteti v 100 in v primeru, ko se ne, se lahko odločimo, da takšne vrstice izbrišemo. Na tem primeru si bomo sedaj pogledali še operacije nad stolpci. Naš cilj bo, da dodamo temu tibblu še en stolpec, v katerem bomo sešteli vse te stolpce.
Funkcija apply
deluje tudi nad stolpci, če spremenimo drugi argument:
tmp <- ds_jobs %>%
select(starts_with("Time"))
head(apply(tmp, 1, sum, na.rm = T))
## [1] 100 100 100 100 0 100
Kako pa to naredimo z dplyr, tako da se bo naravno vključilo v potek dela? Prva ideja bi morda bila, da enostavno naštejemo vse stolpce.
ds_jobs %>%
select(Country, CurrentJobTitle, starts_with("Time")) %>%
mutate(TotalTime = TimeGatheringData + TimeModelBuilding + TimeProduction +
TimeVisualizing + TimeFindingInsights + TimeOtherSelect) %>%
select(!starts_with("Time")) # Ta vrstica je samo za lepši izpis.
## # A tibble: 3,781 × 3
## Country CurrentJobTitle TotalTime
## <chr> <chr> <dbl>
## 1 Australia Business Analyst 100
## 2 Russia Software Developer/Software Engineer 100
## 3 Taiwan Software Developer/Software Engineer 100
## 4 United States Researcher 100
## 5 United States Scientist/Researcher 0
## 6 Czech Republic Other 100
## 7 Russia Data Analyst 100
## 8 Colombia Data Scientist 100
## 9 Germany Data Scientist 100
## 10 Poland Software Developer/Software Engineer 100
## # … with 3,771 more rows
Sicer je to v našem primeru bilo izvedljivo, saj smo imeli samo 6 stolpcev. Kako pa bi to naredili z večimi stolpci? Morda lahko uporabimo starts_with()
:
ds_jobs %>%
select(Country, CurrentJobTitle, starts_with("Time")) %>%
mutate(TimeTotal = sum(starts_with("Time"), na.rm = T))
## Error: Problem with `mutate()` column `TimeTotal`.
## ℹ `TimeTotal = sum(starts_with("Time"), na.rm = T)`.
## x `starts_with()` must be used within a *selecting* function.
## ℹ See <https://tidyselect.r-lib.org/reference/faq-selection-context.html>.
R vrne napako in nas opozori, da se lahko starts_with()
uporabi le znotraj izbire. Če želimo v tem primeru omogočiti urejeno izbiro stolpcev, uporabimo funkcijo c_across()
. Ta funkcija je po funkcionalnosti bolj podobna funkciji c()
ali select()
, kot pa funkciji across()
, tako da jih ne smemo zamenjati:
ds_jobs %>%
select(Country, CurrentJobTitle, starts_with("Time")) %>%
mutate(TotalTime = sum(c_across(starts_with("Time")), na.rm = T)) %>%
select(!starts_with("Time"))
## # A tibble: 3,781 × 3
## Country CurrentJobTitle TotalTime
## <chr> <chr> <dbl>
## 1 Australia Business Analyst 375462
## 2 Russia Software Developer/Software Engineer 375462
## 3 Taiwan Software Developer/Software Engineer 375462
## 4 United States Researcher 375462
## 5 United States Scientist/Researcher 375462
## 6 Czech Republic Other 375462
## 7 Russia Data Analyst 375462
## 8 Colombia Data Scientist 375462
## 9 Germany Data Scientist 375462
## 10 Poland Software Developer/Software Engineer 375462
## # … with 3,771 more rows
Sedaj smo dobili nek rezultat, ki pa še vedno ni pravilen. V čem je težava? Če sum()
uporabimo znotraj mutate()
, ta vrne vsoto znotraj skupin, določenih z group_by()
. Ker podatkov nismo grupirali, vrne vsoto kar čez celotne podatke. Rešitev se torej skriva v ustreznem združevanju vrstic. V dplyr obstaja funkcija, ki celoten tibble grupira po posameznih vrsticah in to je rowwise()
:
ds_jobs %>%
select(Country, CurrentJobTitle, starts_with("Time")) %>%
rowwise() %>%
mutate(TotalTime = sum(c_across(starts_with("Time")), na.rm = T)) %>%
select(!starts_with("Time"))
## # A tibble: 3,781 × 3
## # Rowwise:
## Country CurrentJobTitle TotalTime
## <chr> <chr> <dbl>
## 1 Australia Business Analyst 100
## 2 Russia Software Developer/Software Engineer 100
## 3 Taiwan Software Developer/Software Engineer 100
## 4 United States Researcher 100
## 5 United States Scientist/Researcher 0
## 6 Czech Republic Other 100
## 7 Russia Data Analyst 100
## 8 Colombia Data Scientist 100
## 9 Germany Data Scientist 100
## 10 Poland Software Developer/Software Engineer 100
## # … with 3,771 more rows
1.14 Dodatek
1.14.1 Zamenjava vrstnega reda stolpcev
Vrstni red stolpcev zamenjamo s funkcijo relocate()
. Ustvarimo najprej manjši tibble:
ds_jobs_select <- ds_jobs %>%
select(Gender:Major)
ds_jobs_select
## # A tibble: 3,781 × 8
## Gender Country Age EmploymentStatus CurrentJobTitle LanguageRecomme…
## <chr> <chr> <int> <chr> <chr> <chr>
## 1 Female Australia 43 Employed full-t… Business Analy… Python
## 2 Male Russia 33 Employed full-t… Software Devel… Python
## 3 Male Taiwan 26 Employed full-t… Software Devel… Python
## 4 Male United States 25 Employed part-t… Researcher Python
## 5 Male United States 33 Employed full-t… Scientist/Rese… Matlab
## 6 Male Czech Republic 21 Employed part-t… Other Python
## 7 Male Russia 22 Employed full-t… Data Analyst Python
## 8 Male Colombia 34 Employed full-t… Data Scientist Python
## 9 Male Germany 41 Independent con… Data Scientist Python
## 10 Male Poland 29 Employed full-t… Software Devel… Python
## # … with 3,771 more rows, and 2 more variables: FormalEducation <chr>,
## # Major <chr>
Če želimo določene stolpce premakniti na začetek, jih enostavno podamo funkciji relocate()
. Dajmo na prvo mesto stolpca Major
in Age
:
ds_jobs_select %>%
relocate(Major, Age)
## # A tibble: 3,781 × 8
## Major Age Gender Country EmploymentStatus CurrentJobTitle LanguageRecomme…
## <chr> <int> <chr> <chr> <chr> <chr> <chr>
## 1 "" 43 Female Austra… Employed full-t… Business Analy… Python
## 2 "Othe… 33 Male Russia Employed full-t… Software Devel… Python
## 3 "Comp… 26 Male Taiwan Employed full-t… Software Devel… Python
## 4 "Phys… 25 Male United… Employed part-t… Researcher Python
## 5 "Elec… 33 Male United… Employed full-t… Scientist/Rese… Matlab
## 6 "Comp… 21 Male Czech … Employed part-t… Other Python
## 7 "Info… 22 Male Russia Employed full-t… Data Analyst Python
## 8 "Comp… 34 Male Colomb… Employed full-t… Data Scientist Python
## 9 "" 41 Male Germany Independent con… Data Scientist Python
## 10 "Comp… 29 Male Poland Employed full-t… Software Devel… Python
## # … with 3,771 more rows, and 1 more variable: FormalEducation <chr>
Poljubno ureditev dobimo tako, da enostavno zapišemo vrstni red stolpcev, kot ga želimo. Funkcija relocate()
omogoča še nekatere možnosti urejanja, kot na primer, glede na tip spremenljivke. Za več informacij o različnih načinih urejanja stolpcev bralcu predlagamo uporabo pomoči ?relocate
.
1.14.2 Preimenovanje stolpcev
Stolpce preimenujemo s funkcijo rename()
.
ds_jobs_select %>%
rename(employment_status = EmploymentStatus,
current_job_title = CurrentJobTitle)
## # A tibble: 3,781 × 8
## Gender Country Age employment_status current_job_title LanguageRecomme…
## <chr> <chr> <int> <chr> <chr> <chr>
## 1 Female Austral… 43 Employed full-time Business Analyst Python
## 2 Male Russia 33 Employed full-time Software Develop… Python
## 3 Male Taiwan 26 Employed full-time Software Develop… Python
## 4 Male United … 25 Employed part-time Researcher Python
## 5 Male United … 33 Employed full-time Scientist/Resear… Matlab
## 6 Male Czech R… 21 Employed part-time Other Python
## 7 Male Russia 22 Employed full-time Data Analyst Python
## 8 Male Colombia 34 Employed full-time Data Scientist Python
## 9 Male Germany 41 Independent contrac… Data Scientist Python
## 10 Male Poland 29 Employed full-time Software Develop… Python
## # … with 3,771 more rows, and 2 more variables: FormalEducation <chr>,
## # Major <chr>
Tibble lahko vsebuje tudi imena stolpcev, ki niso veljavna za spremenljivke v R. V tem primeru jih moramo zapisati znotraj `
. Na primer, spremenljivki v R ne moremo prirediti imena z minusom. Poizkusimo to narediti v tibblu:
ds_jobs_select %>%
rename(`employment-status` = EmploymentStatus,
`current-job-title` = CurrentJobTitle)
## # A tibble: 3,781 × 8
## Gender Country Age `employment-status` `current-job-tit… LanguageRecomme…
## <chr> <chr> <int> <chr> <chr> <chr>
## 1 Female Austral… 43 Employed full-time Business Analyst Python
## 2 Male Russia 33 Employed full-time Software Develop… Python
## 3 Male Taiwan 26 Employed full-time Software Develop… Python
## 4 Male United … 25 Employed part-time Researcher Python
## 5 Male United … 33 Employed full-time Scientist/Resear… Matlab
## 6 Male Czech R… 21 Employed part-time Other Python
## 7 Male Russia 22 Employed full-time Data Analyst Python
## 8 Male Colombia 34 Employed full-time Data Scientist Python
## 9 Male Germany 41 Independent contrac… Data Scientist Python
## 10 Male Poland 29 Employed full-time Software Develop… Python
## # … with 3,771 more rows, and 2 more variables: FormalEducation <chr>,
## # Major <chr>
1.14.3 Summarise in group unpeeling
Kot smo že spoznali je funkcija summarise()
najbolj uporabna v kombinaciji z group_by()
. Poglejmo si sedaj bolj podrobno, kakšen tibble je rezultat te kombinacije. Najprej samo grupirajmo ds_jobs
:
ds_jobs_grouped <- ds_jobs %>%
group_by(FormalEducation, EmploymentStatus)
ds_jobs_grouped
## # A tibble: 3,781 × 19
## # Groups: FormalEducation, EmploymentStatus [21]
## Gender Country Age EmploymentStatus CurrentJobTitle LanguageRecomme…
## <chr> <chr> <int> <chr> <chr> <chr>
## 1 Female Australia 43 Employed full-t… Business Analy… Python
## 2 Male Russia 33 Employed full-t… Software Devel… Python
## 3 Male Taiwan 26 Employed full-t… Software Devel… Python
## 4 Male United States 25 Employed part-t… Researcher Python
## 5 Male United States 33 Employed full-t… Scientist/Rese… Matlab
## 6 Male Czech Republic 21 Employed part-t… Other Python
## 7 Male Russia 22 Employed full-t… Data Analyst Python
## 8 Male Colombia 34 Employed full-t… Data Scientist Python
## 9 Male Germany 41 Independent con… Data Scientist Python
## 10 Male Poland 29 Employed full-t… Software Devel… Python
## # … with 3,771 more rows, and 13 more variables: FormalEducation <chr>,
## # Major <chr>, CompensationAmount <dbl>, CompensationCurrency <chr>,
## # TimeGatheringData <int>, TimeModelBuilding <dbl>, TimeProduction <dbl>,
## # TimeVisualizing <dbl>, TimeFindingInsights <dbl>, TimeOtherSelect <int>,
## # ExchangeRate <dbl>, CompensationUSD <dbl>, MonthlyCompUSD <dbl>
V drugi vrstici vidimo, da je ta tibble grupiran po spremenljivkah FormalEducation
in EmploymentStatus
. Poglejmo kaj se zgodi, ko uporabimo summarise()
:
ds_jobs_summarised <- ds_jobs_grouped %>%
summarise(Count = n())
ds_jobs_summarised
## # A tibble: 21 × 3
## # Groups: FormalEducation [8]
## FormalEducation EmploymentStatus Count
## <chr> <chr> <int>
## 1 "" Employed full-time 1
## 2 "Bachelor's degree" Employed full-time 857
## 3 "Bachelor's degree" Employed part-time 52
## 4 "Bachelor's degree" Independent contractor, freelanc… 76
## 5 "Doctoral degree" Employed full-time 719
## 6 "Doctoral degree" Employed part-time 26
## 7 "Doctoral degree" Independent contractor, freelanc… 50
## 8 "I did not complete any formal educa… Employed full-time 13
## 9 "I did not complete any formal educa… Employed part-time 2
## 10 "I did not complete any formal educa… Independent contractor, freelanc… 10
## # … with 11 more rows
Opazimo, da je ta novi tibble grupiran samo po spremenljivki FormalEducation
. Privzeto summarise()
vedno odstrani zadnje grupiranje. Če tega ne želimo, lahko uporabimo dodaten parameter .groups = "keep"
.
ds_jobs_summarised <- ds_jobs_grouped %>%
summarise(Count = n(), .groups = "keep")
ds_jobs_summarised
## # A tibble: 21 × 3
## # Groups: FormalEducation, EmploymentStatus [21]
## FormalEducation EmploymentStatus Count
## <chr> <chr> <int>
## 1 "" Employed full-time 1
## 2 "Bachelor's degree" Employed full-time 857
## 3 "Bachelor's degree" Employed part-time 52
## 4 "Bachelor's degree" Independent contractor, freelanc… 76
## 5 "Doctoral degree" Employed full-time 719
## 6 "Doctoral degree" Employed part-time 26
## 7 "Doctoral degree" Independent contractor, freelanc… 50
## 8 "I did not complete any formal educa… Employed full-time 13
## 9 "I did not complete any formal educa… Employed part-time 2
## 10 "I did not complete any formal educa… Independent contractor, freelanc… 10
## # … with 11 more rows
1.15 Ali želite izvedeti več?
V tem poglavju smo spoznali temeljne operacije nad podatki in njihovo implementacijo v R paketu dplyr. Opis vseh funkcij v dplyr najdemo tukaj: https://dplyr.tidyverse.org/reference/index.html. Jedrnat povzetek pa je na voljo tukaj, pod poglavjem Data Transformation Cheatsheet: https://www.rstudio.com/resources/cheatsheets/.
1.16 Domača naloga
Začeli bomo z relativno preprosto nalogo, kjer bomo ponovili osnovne ukaze iz slovnice ravnanja s podatki. Osnovna različica programskega jezika R že vsebuje nekatere podatkovne zbirke. Z ukazom
data()
dobimo opis vseh zbirk. V tej nalogi bomo uporabili podatkovno zbirkomtcars
:head(mtcars)
## mpg cyl disp hp drat wt qsec vs am gear carb ## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 ## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 ## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 ## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 ## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 ## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
Za podrobnejši opis podatkov uporabite pomoč
?mtcars
. Najprej ustvarite novo spremenljivkomtcars_tib
, v katero shranite razpredelnicomtcars
kot tibble. Nato vsako izmed spodnjih nalog izvedite posebej (torej v vsaki točki izvedite ukaz namtcars_tib
, ampak tako spremenjenega tibbla ne shranite nazaj v to spremenljivko), razen če je v nalogi eksplicitno navedeno drugače. Vaše naloge so sledeče:- Ustvarite novo spremenljivko
mtcars_tib
, v katero shranite razpredelnicomtcars
kot tibble. - Izberite vse vrstice avtomobilov z avtomatskim menjalnikom.
## # A tibble: 19 × 11 ## mpg cyl disp hp drat wt qsec vs am gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1 ## 2 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2 ## 3 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1 ## 4 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4 ## 5 24.4 4 147. 62 3.69 3.19 20 1 0 4 2 ## 6 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2 ## 7 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4 ## 8 17.8 6 168. 123 3.92 3.44 18.9 1 0 4 4 ## 9 16.4 8 276. 180 3.07 4.07 17.4 0 0 3 3 ## 10 17.3 8 276. 180 3.07 3.73 17.6 0 0 3 3 ## 11 15.2 8 276. 180 3.07 3.78 18 0 0 3 3 ## 12 10.4 8 472 205 2.93 5.25 18.0 0 0 3 4 ## 13 10.4 8 460 215 3 5.42 17.8 0 0 3 4 ## 14 14.7 8 440 230 3.23 5.34 17.4 0 0 3 4 ## 15 21.5 4 120. 97 3.7 2.46 20.0 1 0 3 1 ## 16 15.5 8 318 150 2.76 3.52 16.9 0 0 3 2 ## 17 15.2 8 304 150 3.15 3.44 17.3 0 0 3 2 ## 18 13.3 8 350 245 3.73 3.84 15.4 0 0 3 4 ## 19 19.2 8 400 175 3.08 3.84 17.0 0 0 3 2
- Izberite vse vrstice, kjer je poraba manjša od 15 galon na miljo ali večja od 20 galon na miljo in je motor oblike V.
## # A tibble: 8 × 11 ## mpg cyl disp hp drat wt qsec vs am gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 21 6 160 110 3.9 2.62 16.5 0 1 4 4 ## 2 21 6 160 110 3.9 2.88 17.0 0 1 4 4 ## 3 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4 ## 4 10.4 8 472 205 2.93 5.25 18.0 0 0 3 4 ## 5 10.4 8 460 215 3 5.42 17.8 0 0 3 4 ## 6 14.7 8 440 230 3.23 5.34 17.4 0 0 3 4 ## 7 13.3 8 350 245 3.73 3.84 15.4 0 0 3 4 ## 8 26 4 120. 91 4.43 2.14 16.7 0 1 5 2
- Izberite vse stolpce, kjer ime stolpca vsebuje črko a.
## # A tibble: 32 × 4 ## drat am gear carb ## <dbl> <dbl> <dbl> <dbl> ## 1 3.9 1 4 4 ## 2 3.9 1 4 4 ## 3 3.85 1 4 1 ## 4 3.08 0 3 1 ## 5 3.15 0 3 2 ## 6 2.76 0 3 1 ## 7 3.21 0 3 4 ## 8 3.69 0 4 2 ## 9 3.92 0 4 2 ## 10 3.92 0 4 4 ## # … with 22 more rows
- Izberite zadnje 4 stolpce.
## # A tibble: 32 × 4 ## vs am gear carb ## <dbl> <dbl> <dbl> <dbl> ## 1 0 1 4 4 ## 2 0 1 4 4 ## 3 1 1 4 1 ## 4 1 0 3 1 ## 5 0 0 3 2 ## 6 1 0 3 1 ## 7 0 0 3 4 ## 8 1 0 4 2 ## 9 1 0 4 2 ## 10 1 0 4 4 ## # … with 22 more rows
- V tibble
mtcars_tib
dodajte stolpca, kjer bosta izračunani število litrov na 100 kilometrov in teža v kilogramih (v tisočicah). 1 milja je približno 1.61 kilometra, 1 galona 3.79 litra in 1 funt 0.45 kilograma.
## # A tibble: 32 × 4 ## mpg wt lp100km wt_in_kg ## <dbl> <dbl> <dbl> <dbl> ## 1 21 2.62 11.2 1.18 ## 2 21 2.88 11.2 1.29 ## 3 22.8 2.32 10.3 1.04 ## 4 21.4 3.22 11.0 1.45 ## 5 18.7 3.44 12.6 1.55 ## 6 18.1 3.46 13.0 1.56 ## 7 14.3 3.57 16.5 1.61 ## 8 24.4 3.19 9.65 1.44 ## 9 22.8 3.15 10.3 1.42 ## 10 19.2 3.44 12.3 1.55 ## # … with 22 more rows
- Izračunajte povprečno porabo avtomobilov v odvisnosti števila cilindrov.
## # A tibble: 3 × 2 ## cyl mean_mpg ## <dbl> <dbl> ## 1 4 26.7 ## 2 6 19.7 ## 3 8 15.1
- Izračunajte povprečno konjsko moč v odvisnosti od oblike motorja in ali je avtomobil avtomatik ali ne.
## # A tibble: 4 × 3 ## # Groups: vs [2] ## vs am mean_hp ## <dbl> <dbl> <dbl> ## 1 0 0 194. ## 2 0 1 181. ## 3 1 0 102. ## 4 1 1 80.6
- Normalizirajte vse stolpce, ki vsebujejo decimalna števila, na interval [0, 1]. To naredimo tako, da vrednostim odštejemo minimalno vrednost in delimo z razliko med maksimalno in minimalno vrednostjo: \[ x_i' = \frac{x_i - \min(x)}{\max(x) - \min(x)}. \]
## # A tibble: 32 × 13 ## mpg cyl disp hp drat wt qsec vs am gear carb lp100km ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 0.451 6 0.222 110 0.525 0.283 0.233 0 1 4 4 0.272 ## 2 0.451 6 0.222 110 0.525 0.348 0.3 0 1 4 4 0.272 ## 3 0.528 4 0.0920 93 0.502 0.206 0.489 1 1 4 1 0.215 ## 4 0.468 6 0.466 110 0.147 0.435 0.588 1 0 3 1 0.259 ## 5 0.353 8 0.721 175 0.180 0.493 0.3 0 0 3 2 0.360 ## 6 0.328 6 0.384 105 0 0.498 0.681 1 0 3 1 0.386 ## 7 0.166 8 0.721 245 0.207 0.526 0.160 0 0 3 4 0.607 ## 8 0.596 4 0.189 62 0.429 0.429 0.655 1 0 4 2 0.172 ## 9 0.528 4 0.174 95 0.535 0.419 1 1 0 4 2 0.215 ## 10 0.374 6 0.241 123 0.535 0.493 0.452 1 0 4 4 0.339 ## # … with 22 more rows, and 1 more variable: wt_in_kg <dbl>
- Izračunajte povprečne vrednosti vseh stolpcev.
## # A tibble: 1 × 13 ## mpg cyl disp hp drat wt qsec vs am gear carb lp100km ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 20.1 6.19 231. 147. 3.60 3.22 17.8 0.438 0.406 3.69 2.81 12.8 ## # … with 1 more variable: wt_in_kg <dbl>
- Ustvarite novo spremenljivko
Težja naloga. V mapi data-raw se nahajajo podatki o gozdnih požarih na Portugalskem. Podatki so bili uporabljeni v znanstvenem članku (Cortez and Morais 2007), kjer so napovedovali velikost požganega območja v odvisnosti od meteoroloških in drugih podatkov. Vrednosti 0 za požgano območje predstavljajo požare, kjer je pogorelo manj kot 100 kvadratnih metrov.
- Preberite podatke in jih shranite kot tibble.
- Preverite, v katerem mesecu je največ požarov in jih uredite padajoče od tistega z največ požari do tistega z najmanj.
## # A tibble: 12 × 2 ## month n ## <chr> <int> ## 1 aug 184 ## 2 sep 172 ## 3 mar 54 ## 4 jul 32 ## 5 feb 20 ## 6 jun 17 ## 7 oct 15 ## 8 apr 9 ## 9 dec 9 ## 10 jan 2 ## 11 may 2 ## 12 nov 1
- Preverite, ali obstajajo območja v parku, kjer se bolj pogosto pojavljajo požari. Za vsako kombinacijo koordinat bomo torej izračunali število požarov. Rezultat lahko predstavimo z razpredelnico. Glede na to, da imamo dvodimenzionalne podatke, bi jih morda bilo smiselno predstaviti vizualno. V kolikor poznate paket ggplot2, predlagamo da si pogledate funkcijo
geom_tile()
.
## # A tibble: 36 × 3 ## X Y n ## <dbl> <dbl> <int> ## 1 1 2 19 ## 2 1 3 10 ## 3 1 4 15 ## 4 1 5 4 ## 5 2 2 25 ## 6 2 3 1 ## 7 2 4 27 ## 8 2 5 20 ## 9 3 3 1 ## 10 3 4 43 ## # … with 26 more rows
- Dodajte stolpec, ki bo za vsak požar izračunal delež požganega območja glede na vse požare na posameznih koordinatah. Za tem smiselno filtrirajte podatke (ali smo v novem stolpcu dobili kakšne nepričakovane, oziroma neveljavne vrednosti?).
## # A tibble: 509 × 5 ## X Y month day area_by_coord ## <dbl> <dbl> <chr> <chr> <dbl> ## 1 7 5 mar fri 0 ## 2 7 4 oct tue 0 ## 3 7 4 oct sat 0 ## 4 8 6 mar fri 0 ## 5 8 6 mar sun 0 ## 6 8 6 aug sun 0 ## 7 8 6 aug mon 0 ## 8 8 6 aug mon 0 ## 9 8 6 sep tue 0 ## 10 7 5 sep sat 0 ## # … with 499 more rows
- Preverite, ali ob vročem vremenu in nizki vlažnosti pogori večji delež območja, ki smo ga izračunali v prejšnji točki, tako da izberete vrstice, kjer je temperatura višja od 0.8 kvantila temperature in vlažnost nižja od 0.2 kvantila vlažnosti ter izračunate povprečje. \(q\)-ti kvantil je ocena števila, za katerega velja, da je \(q\) vrednosti manjših od tega števila. Za računanje kvantilov uporabite funkcijo
quantile()
. Za primerjavo izračunajte še povprečje te spremenljivke za vse preostale vrstice. Ali se rezultati skladajo z vašo intuicijo?
## # A tibble: 1 × 1 ## mean_area_by_coord ## <dbl> ## 1 0.153
## # A tibble: 1 × 1 ## mean_area_by_coord ## <dbl> ## 1 0.0555
- Izračunajte povprečje standardiziranih indeksov in ga vstavite kot stolpec pred prvo spremenljivko, ki predstavlja indeks.
## # A tibble: 509 × 15 ## # Rowwise: ## X Y month day mean_indices FFMC_index DMC_index DC_index ISI_index ## <dbl> <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 7 5 mar fri -1.21 -0.796 -1.32 -1.86 -0.859 ## 2 7 4 oct tue -0.304 -0.00502 -1.18 0.480 -0.510 ## 3 7 4 oct sat -0.254 -0.00502 -1.05 0.552 -0.510 ## 4 8 6 mar fri -0.739 0.193 -1.21 -1.92 -0.00890 ## 5 8 6 mar sun -0.719 -0.239 -0.934 -1.82 0.122 ## 6 8 6 aug sun 0.218 0.301 -0.405 -0.256 1.23 ## 7 8 6 aug mon -0.0979 0.301 -0.349 -0.225 -0.118 ## 8 8 6 aug mon 0.320 0.157 0.530 0.232 0.361 ## 9 8 6 sep tue 0.120 0.0669 0.283 0.575 -0.445 ## 10 7 5 sep sat 0.0375 0.337 -0.363 0.599 -0.423 ## # … with 499 more rows, and 6 more variables: temp <dbl>, RH <dbl>, wind <dbl>, ## # rain <dbl>, area <dbl>, area_by_coord <dbl>