12 Primjer upravljanja podacima
Ovdje će se prikazati osnove upravljanja podacima na datasetu ‘starwars’ iz paketa dplyr (Yarberry and Yarberry 2021). Ovo poglavlje pruža praktičan uvid u primjenu tehnika upravljanja podacima u R-u, koristeći dataset starwars iz paketa dplyr. Kroz primjere se ilustrira kako pristupiti podacima, odabrati i filtrirati relevantne varijable te kako raditi s podacima koji nedostaju. Posebna pažnja posvećena je osnovnim tehnikama čišćenja podataka: zamjena vrijednosti koje nedostaju, formatiranje podataka te pretvaranje višestrukih unosa u jedinstvene zapise. Prikazani su primjeri kako se koristiti složenim tabličnim prikazima, poput tablica kontingencije, dok se dodatnim statističkim izračunima i vizualizacijama analizira raspodjela i povezanost unutar podataka.
> library(tidyverse)
> library(dplyr)
> data("starwars")
> data("starwars")
> glimpse(starwars)
## Rows: 87
## Columns: 14
## $ name <chr> "Luke Skywalker", "C-3PO", "R2-D2", "Darth Vader", "Leia Or…
## $ height <int> 172, 167, 96, 202, 150, 178, 165, 97, 183, 182, 188, 180, 2…
## $ mass <dbl> 77, 75, 32, 136, 49, 120, 75, 32, 84, 77, 84, NA, 112, 80, …
## $ hair_color <chr> "blond", NA, NA, "none", "brown", "brown, grey", "brown", N…
## $ skin_color <chr> "fair", "gold", "white, blue", "white", "light", "light", "…
## $ eye_color <chr> "blue", "yellow", "red", "yellow", "brown", "blue", "blue",…
## $ birth_year <dbl> 19, 112, 33, 42, 19, 52, 47, NA, 24, 57, 42, 64, 200, 29, 4…
## $ sex <chr> "male", "none", "none", "male", "female", "male", "female",…
## $ gender <chr> "masculine", "masculine", "masculine", "masculine", "femini…
## $ homeworld <chr> "Tatooine", "Tatooine", "Naboo", "Tatooine", "Alderaan", "T…
## $ species <chr> "Human", "Droid", "Droid", "Human", "Human", "Human", "Huma…
## $ films <list> <"A New Hope", "The Empire Strikes Back", "Return of the J…
## $ vehicles <list> <"Snowspeeder", "Imperial Speeder Bike">, <>, <>, <>, "Imp…
## $ starships <list> <"X-wing", "Imperial shuttle">, <>, <>, "TIE Advanced x1",…
Prvo, vidimo da podatkovni okvir sadrži 14 varijabli sa 87 opažanja:
- varijabla ime je tipa „character”, kao što i očekujemo
- varijabla visine je numerička cjelobrojna varijabla, „int”
- varijabla masa/ težina je numerička varijable, „double”
- varijable boja kose, boja kože, boja očiju, spol, rod, planet s kojeg potječu i vrsta su tipa „character
- filmovi, vozila i svemirski brodovi su liste
Dodatni uvid u strukturu podataka:
> head(starwars)
## # A tibble: 6 × 14
## name height mass hair_color skin_color eye_color birth_year sex gender
## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Luke Sky… 172 77 blond fair blue 19 male mascu…
## 2 C-3PO 167 75 <NA> gold yellow 112 none mascu…
## 3 R2-D2 96 32 <NA> white, bl… red 33 none mascu…
## 4 Darth Va… 202 136 none white yellow 41.9 male mascu…
## 5 Leia Org… 150 49 brown light brown 19 fema… femin…
## 6 Owen Lars 178 120 brown, gr… light blue 52 male mascu…
## # ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
## # vehicles <list>, starships <list>
Ovdje ćemo se detaljnije pozabaviti podatkovnim okvirom, pa ćemo odabrati nekoliko varijabli za daljnje uvide. Odabirom stupaca s određenim varijablama (bilo putem rednih brojeva stupaca ili naziva) kreirat ćemo novi podatkovni skup.
> Starwars <- as.data.frame(starwars[,c(1:4,6,10,11)])
> glimpse(Starwars)
## Rows: 87
## Columns: 7
## $ name <chr> "Luke Skywalker", "C-3PO", "R2-D2", "Darth Vader", "Leia Or…
## $ height <int> 172, 167, 96, 202, 150, 178, 165, 97, 183, 182, 188, 180, 2…
## $ mass <dbl> 77, 75, 32, 136, 49, 120, 75, 32, 84, 77, 84, NA, 112, 80, …
## $ hair_color <chr> "blond", NA, NA, "none", "brown", "brown, grey", "brown", N…
## $ eye_color <chr> "blue", "yellow", "red", "yellow", "brown", "blue", "blue",…
## $ homeworld <chr> "Tatooine", "Tatooine", "Naboo", "Tatooine", "Alderaan", "T…
## $ species <chr> "Human", "Droid", "Droid", "Human", "Human", "Human", "Huma…
Provjeru podataka koji nedostaju izvršit ćemo kombinacijom dvije funkcije, summary()
i is.na()
. Druga funkcija služi provjeri nalaze li se u varijabli NA (vrijednosti koje nedostaju), a summary()
će poslužiti za jasan prikaz.
> summary(is.na(Starwars))
## name height mass hair_color
## Mode :logical Mode :logical Mode :logical Mode :logical
## FALSE:87 FALSE:81 FALSE:59 FALSE:82
## TRUE :6 TRUE :28 TRUE :5
## eye_color homeworld species
## Mode :logical Mode :logical Mode :logical
## FALSE:87 FALSE:77 FALSE:83
## TRUE :10 TRUE :4
Za 6 likova nedostaje podatak o visini, za 28 nedostaje podatak o težini, za 5 nedostaje podatak o boji kose…. Ukratko, is.na(starwars) provjerava je li vrijednost prisutna (FALSE) ili nedostaje (TRUE), dok summary te podatke sažima u zbroj podataka koji su navedeni i onih koji nedostaju.
Recimo da pretpostavljamo da bismo mogli znati podatke koji nedostaju o vrsti, pa želimo identificirati gdje se nalaze NA, kako bismo ih eventualno izmijenili.
> na_pozicije <- which(is.na(Starwars$species))
> na_pozicije
## [1] 18 59 60 81
NA se nalaze na pozicijama 18, 59, 60 i 81. Moramo provjeriti o kojim se likovima radi.
> Starwars$name[na_pozicije]
## [1] "Jek Tono Porkins" "Gregar Typho" "Cord\xe9" "Sly Moore"
Kratkim pretraživanjem, možemo saznati kojim vrstama pripadaju ovi likovi:
- Jek Tono Porkins: Human
- Gregar Typho: Human
- Cordé: Human
- Sly Moore: Umbaran
Sada možemo zamijeniti postojeće NA poznatim podacima. To možemo učiniti na dva načina. S obzirom da ih je malo, možemo koristiti „ručni” unos:
> Starwars$species[18] <- "Human"
> Starwars$species[59] <- "Human"
> Starwars$species[60] <- "Human"
> Starwars$species[81] <- "Umbaran"
Provjera:
> summary(is.na(Starwars$species))
## Mode FALSE
## logical 87
Svi su podaci uspješno zamijenjeni i ta varijabla više ne sadrži NA. Kad bi u pitanju bilo više vrijednosti, onda bi bilo praktičnije prvo kreirati vektor koji mapira imena likova na njihove vrste. Potom bi se koristila petlja for ili vektorizirana funkcija za pregled redova u podatkovnom okviru i zamijenile NA vrijednosti odgovarajućim vrstama:
> species_replacements <- c("Jek Tono Porkins" = "Human",
+ "Gregar Typho" = "Human",
+ "Cordé" = "Human",
+ "Sly Moore" = "Umbaran")
> for (name in names(species_replacements)) {
+ na_indices <- is.na(Starwars$species) & Starwars$name == name
+ Starwars$species[na_indices] <- species_replacements[name]
+ }
Ovaj kod prvo identificira redove u kojima je species NA i gdje se ime lika podudara s ključem u species_replacements. Zatim zamjenjuje NA odgovarajućom vrstom.
Sljedeće, provjeravamo za boju kose.
> na_pozicije <- which(is.na(Starwars$hair_color))
> na_pozicije
## [1] 2 3 8 15 16
> Starwars$name[na_pozicije]
## [1] "C-3PO" "R2-D2" "R5-D4"
## [4] "Greedo" "Jabba Desilijic Tiure"
Za navedene likove boja kose nije primjenjiva. Kako se ne bismo bavili s NA, možemo ih zamijeniti s, na primjer „Unknown” i odmah provjeriti provedbu zamjene.
> Starwars$hair_color[na_pozicije]<- "Unknown"
>
> summary(is.na(Starwars$hair_color))
## Mode FALSE
## logical 87
> unique(Starwars$hair_color)
## [1] "blond" "Unknown" "none" "brown"
## [5] "brown, grey" "black" "auburn, white" "auburn, grey"
## [9] "white" "grey" "auburn" "blonde"
Druga stvar koja se može primijetiti kod boje kose jest da se pojavljuje Unknown i unknown kao zasebna „boja”, iako se radi o pojmovno istoj stvari. To je zbog toga što je R osjetljiv na velika i mala slova. No to možemo jednostavno riješiti tako što ćemo sve znakove u varijabli hair_color podesiti na mala slova.
> Starwars$hair_color<-tolower(Starwars$hair_color)
> unique(Starwars$hair_color)
## [1] "blond" "unknown" "none" "brown"
## [5] "brown, grey" "black" "auburn, white" "auburn, grey"
## [9] "white" "grey" "auburn" "blonde"
Druga stvar koju se može primijetiti kod boje kose jest da da su za neke likove zapisane dvije boje. Recimo da želimo zadržati samo prvu zapisanu boju. To znači da prvo moramo razdvojiti zapisane boje, a potom pohraniti prvu boju u varijablu hair_color.
> hair_colors_first <- sapply(strsplit(Starwars$hair_color, ", "), `[`, 1)
> hair_colors_first
## [1] "blond" "unknown" "unknown" "none" "brown" "brown" "brown"
## [8] "unknown" "black" "auburn" "blond" "auburn" "brown" "brown"
## [15] "unknown" "unknown" "brown" "brown" "white" "grey" "black"
## [22] "none" "none" "black" "none" "none" "auburn" "brown"
## [29] "brown" "none" "brown" "none" "blond" "brown" "none"
## [36] "none" "none" "brown" "black" "none" "black" "black"
## [43] "none" "none" "none" "none" "none" "none" "none"
## [50] "none" "white" "none" "black" "none" "none" "none"
## [57] "none" "none" "black" "brown" "brown" "none" "black"
## [64] "black" "brown" "white" "black" "black" "blonde" "none"
## [71] "none" "none" "white" "none" "none" "none" "none"
## [78] "none" "brown" "brown" "none" "none" "black" "brown"
## [85] "brown" "none" "none"
> Starwars$hair_color <- hair_colors_first
> unique(Starwars$hair_color)
## [1] "blond" "unknown" "none" "brown" "black" "auburn" "white"
## [8] "grey" "blonde"
Uočavamo još dvije stvari: blond i blonde su sinonimi, stoga i to treba korigirati. Također, unknown i none bi također mogli biti vezani za istu situaciju te none možemo zamijeniti s unknown.
> # Zamjena "blond" s "blonde"
> Starwars$hair_color <- gsub("\\bblond\\b", "blonde", Starwars$hair_color)
> # \\b označava granicu riječi, što osigurava da se zamjena dogodi samo onda
> #kada se „blond" pojavljuje kao zasebna riječ, a ne kao dio druge riječi
>
> # Zamjena „none" s „unknown"
> Starwars$hair_color <- gsub("none", "unknown", Starwars$hair_color)
>
> unique(Starwars$hair_color)
## [1] "blonde" "unknown" "brown" "black" "auburn" "white" "grey"
Ovime smo završili čišćenje podataka u varijabli hair_color. Daljnja analiza ovisi o kvaliteti podataka. Ako podaci nisu pravilno zapisani, potrebno je provesti „čišćenje” podataka, na način da se podaci ne ujednače na pravilan način, riješi se pitanje NA, definira prikladan tip varijable i slično.
Recimo da nas zbunjuje korištenje engleskih naziva i zbog toga želimo promijeniti nazive varijabli u podatkovnom okviru.
> colnames(Starwars) <-c("ime", "visina", "tezina",
+ "boja_kose", "boja_ociju",
+ "planet", "vrsta")
> str(Starwars)
## 'data.frame': 87 obs. of 7 variables:
## $ ime : chr "Luke Skywalker" "C-3PO" "R2-D2" "Darth Vader" ...
## $ visina : int 172 167 96 202 150 178 165 97 183 182 ...
## $ tezina : num 77 75 32 136 49 120 75 32 84 77 ...
## $ boja_kose : chr "blonde" "unknown" "unknown" "unknown" ...
## $ boja_ociju: chr "blue" "yellow" "red" "yellow" ...
## $ planet : chr "Tatooine" "Tatooine" "Naboo" "Tatooine" ...
## $ vrsta : chr "Human" "Droid" "Droid" "Human" ...
Recimo da nas zanima koliko iznosi prosječna visina i težina za svaku vrstu. Prvo bismo morali provjeriti koliko ima različitih vrsta, a potom za svaku izračunati visinu i težinu. Nakon toga, mogli bismo to prikazati u tablici.
> unique(Starwars$vrsta)
## [1] "Human" "Droid" "Wookiee" "Rodian"
## [5] "Hutt" "Yoda's species" "Trandoshan" "Mon Calamari"
## [9] "Ewok" "Sullustan" "Neimodian" "Gungan"
## [13] "Toydarian" "Dug" "Zabrak" "Twi'lek"
## [17] "Aleena" "Vulptereen" "Xexto" "Toong"
## [21] "Cerean" "Nautolan" "Tholothian" "Iktotchi"
## [25] "Quermian" "Kel Dor" "Chagrian" "Geonosian"
## [29] "Mirialan" "Clawdite" "Besalisk" "Kaminoan"
## [33] "Skakoan" "Muun" "Togruta" "Kaleesh"
## [37] "Umbaran" "Pau'an"
Koristeći naredbu unique()
, utvrđujemo da postoji 38 jedinstvenih naziva za vrste. No, izgledno je da će se neke vrste pojavljivati samo jedanput. Za njih nećemo računati prosječne vrijednosti. To znači da prvo moramo utvrditi frekvencije pojavljivanja vrsta. To možemo učiniti na sljedeći način.
> vrsta_frekv <- table(Starwars$vrsta)
> vrsta_frekv
##
## Aleena Besalisk Cerean Chagrian Clawdite
## 1 1 1 1 1
## Droid Dug Ewok Geonosian Gungan
## 6 1 1 1 3
## Human Hutt Iktotchi Kaleesh Kaminoan
## 38 1 1 1 2
## Kel Dor Mirialan Mon Calamari Muun Nautolan
## 1 2 1 1 1
## Neimodian Pau'an Quermian Rodian Skakoan
## 1 1 1 1 1
## Sullustan Tholothian Togruta Toong Toydarian
## 1 1 1 1 1
## Trandoshan Twi'lek Umbaran Vulptereen Wookiee
## 1 2 1 1 2
## Xexto Yoda's species Zabrak
## 1 1 2
> vrsta_multiple <- which(vrsta_frekv > 1)
> vrsta_multiple_nazivi <- names(vrsta_multiple)
> vrsta_multiple_nazivi
## [1] "Droid" "Gungan" "Human" "Kaminoan" "Mirialan" "Twi'lek" "Wookiee"
## [8] "Zabrak"
Za svaku od ovih vrsta izračunat ćemo prosjek visine i težine temeljem podskupa podataka samo za tu vrstu. To se može učiniti na više načina, a ovdje će se prikazati dva načina.
U prvom slučaju koristimo dplyr paket i filtriranje skupa podataka, a potom grupiranje i sažimanje.
> filtered_data <- Starwars %>%
+ filter(vrsta %in% vrsta_multiple_nazivi)
>
> prosjek_visina_tezina <- filtered_data %>%
+ group_by(vrsta) %>%
+ summarise(
+ prosjek_visina = mean(visina, na.rm = TRUE),
+ prosjek_tezina = mean(tezina, na.rm = TRUE)
+ )
> prosjek_visina_tezina
## # A tibble: 8 × 3
## vrsta prosjek_visina prosjek_tezina
## <chr> <dbl> <dbl>
## 1 Droid 131. 69.8
## 2 Gungan 209. 74
## 3 Human 178. 82.8
## 4 Kaminoan 221 88
## 5 Mirialan 168 53.1
## 6 Twi'lek 179 55
## 7 Wookiee 231 124
## 8 Zabrak 173 80
Alternativno, možemo koristiti pristup „pješke” upotrebom podskupa podataka. Na taj način izračunavamo prosjek visine za pojedinu vrstu temeljem filtracije za jednu vrstu. Isto to učinimo za težinu, a potom ponovimo postupak za preostale vrste. Na kraju objedinimo podatke u tablicu.
> prosjek_visine_Droid <- mean(Starwars$visina[Starwars$vrsta=="Droid"],
+ na.rm = TRUE)
>
> # Ovdje moramo koristiti 'na.rm = TRUE' zato jer varijable
> # visine i težine sadrže nepoznanice koje nismo korigirali
> # zbog na.rm će funkcija mean() ignorirati vrijednosti koje nedostaju;
> # u suprotnom bismo dobili NA ili error
>
> prosjek_tezine_Droid <- mean(Starwars$tezina[Starwars$vrsta=="Droid"],
+ na.rm = TRUE)
>
> prosjek_visine_Gungan <- mean(Starwars$visina[Starwars$vrsta=="Gungan"],
+ na.rm = TRUE)
> prosjek_tezine_Gungan <- mean(Starwars$tezina[Starwars$vrsta=="Gungan"],
+ na.rm = TRUE)
>
> prosjek_visine_Human <- mean(Starwars$visina[Starwars$vrsta=="Human"],
+ na.rm = TRUE)
> prosjek_tezine_Human <- mean(Starwars$tezina[Starwars$vrsta=="Human"],
+ na.rm = TRUE)
>
> prosjek_visine_Kaminoan <- mean(Starwars$visina[Starwars$vrsta=="Kaminoan"],
+ na.rm = TRUE)
> prosjek_tezine_Kaminoan <- mean(Starwars$tezina[Starwars$vrsta=="Kaminoan"],
+ na.rm = TRUE)
>
> prosjek_visine_Mirialan <- mean(Starwars$visina[Starwars$vrsta=="Mirialan"],
+ na.rm = TRUE)
> prosjek_tezine_Mirialan <- mean(Starwars$tezina[Starwars$vrsta=="Mirialan"],
+ na.rm = TRUE)
>
> prosjek_visine_Twilek <- mean(Starwars$visina[Starwars$vrsta=="Twi'lek"],
+ na.rm = TRUE)
> prosjek_tezine_Twilek <- mean(Starwars$tezina[Starwars$vrsta=="Twi'lek"],
+ na.rm = TRUE)
>
> prosjek_visine_Wookiee <- mean(Starwars$visina[Starwars$vrsta=="Wookiee"],
+ na.rm = TRUE)
> prosjek_tezine_Wookiee <- mean(Starwars$tezina[Starwars$vrsta=="Wookiee"],
+ na.rm = TRUE)
>
> prosjek_visine_Zabrak <- mean(Starwars$visina[Starwars$vrsta=="Zabrak"],
+ na.rm = TRUE)
> prosjek_tezine_Zabrak<- mean(Starwars$tezina[Starwars$vrsta=="Zabrak"],
+ na.rm = TRUE)
>
> # Kreiramo tablicu prikaza
>
> visina_tezina_vrsta <-matrix(c("Droid",
+ prosjek_visine_Droid, prosjek_tezine_Droid,
+ "Gungan",
+ prosjek_visine_Gungan, prosjek_tezine_Gungan,
+ "Human",
+ prosjek_visine_Human, prosjek_tezine_Human,
+ "Kaminoan",
+ prosjek_visine_Kaminoan, prosjek_tezine_Kaminoan,
+ "Mirialan",
+ prosjek_visine_Mirialan, prosjek_tezine_Mirialan,
+ "Twi'lek",
+ prosjek_visine_Twilek, prosjek_tezine_Twilek,
+ "Wookiee",
+ prosjek_visine_Wookiee, prosjek_tezine_Wookiee,
+ "Zabrak",
+ prosjek_visine_Zabrak, prosjek_tezine_Zabrak),
+ nrow = 8, byrow = TRUE)
>
> colnames(visina_tezina_vrsta) <- c("Vrsta", "Prosječna visina",
+ "Prosječna težina")
>
> visina_tezina_vrsta<-as.table(visina_tezina_vrsta)
> visina_tezina_vrsta
## Vrsta Prosječna visina Prosječna težina
## A Droid 131.2 69.75
## B Gungan 208.666666666667 74
## C Human 177.636363636364 82.7818181818182
## D Kaminoan 221 88
## E Mirialan 168 53.1
## F Twi'lek 179 55
## G Wookiee 231 124
## H Zabrak 173 80
Rezultat je isti, iako je prvi pristup puno brži. No, ako preferirate pratiti izračune „korak po korak”, drugi pristup će vam biti prihvatljiviji unatoč većem broju linija koda.
Recimo da bismo htjeli vizualno prikazati distribucije visina po vrstama i pretpostavljamo da su visine normalno distribuirane varijable za svaku od vrsta. U tom slučaju, potrebna nam je standardna devijacija za svaku vrstu.
Treba napomenuti da ovo činimo zbog primjera za vježbu i grafičkog prikaza te u inferencijalnoj statistici nećete običavati koristiti podatke ovako malih uzoraka da biste pretpostavljali distribuciju bilo koje karakteristike čitave vrste ili bilo koje veće populacije.
> prosjek_sd_visina <- filtered_data %>%
+ group_by(vrsta) %>%
+ summarise(
+ prosjek_visina = mean(visina, na.rm = TRUE),
+ sd_visina = sd(visina, na.rm = TRUE)
+ )
> prosjek_sd_visina
## # A tibble: 8 × 3
## vrsta prosjek_visina sd_visina
## <chr> <dbl> <dbl>
## 1 Droid 131. 49.1
## 2 Gungan 209. 14.2
## 3 Human 178. 12.1
## 4 Kaminoan 221 11.3
## 5 Mirialan 168 2.83
## 6 Twi'lek 179 1.41
## 7 Wookiee 231 4.24
## 8 Zabrak 173 2.83
> Droidi <- density(rnorm(1000,prosjek_sd_visina$prosjek_visina[1],
+ prosjek_sd_visina$sd_visina[1]))
> Gungan <- density(rnorm(1000,prosjek_sd_visina$prosjek_visina[2],
+ prosjek_sd_visina$sd_visina[2]))
> Human <- density(rnorm(1000,prosjek_sd_visina$prosjek_visina[3],
+ prosjek_sd_visina$sd_visina[3]))
> Kaminoan <- density(rnorm(1000,prosjek_sd_visina$prosjek_visina[4],
+ prosjek_sd_visina$sd_visina[4]))
> Mirialan <- density(rnorm(1000,prosjek_sd_visina$prosjek_visina[5],
+ prosjek_sd_visina$sd_visina[5]))
> Twilek <- density(rnorm(1000,prosjek_sd_visina$prosjek_visina[6],
+ prosjek_sd_visina$sd_visina[6]))
> Wookiee <- density(rnorm(1000,prosjek_sd_visina$prosjek_visina[7],
+ prosjek_sd_visina$sd_visina[7]))
> Zabrak <- density(rnorm(1000,prosjek_sd_visina$prosjek_visina[8],
+ prosjek_sd_visina$sd_visina[8]))
>
> plot(Droidi, main="Visine vrsta", xlab="Visina", ylab="Gustoća",
+ col="red", lwd=2, xlim=c(25,275), ylim=c(0,0.3))
> lines(Gungan, col="blue", lwd=2)
> lines(Human, col="green", lwd=2)
> lines(Kaminoan, col="yellow", lwd=2)
> lines(Mirialan, col="orange", lwd=2)
> lines(Twilek, col="purple", lwd=2)
> lines(Wookiee, col="brown", lwd=2)
> lines(Zabrak, col="pink", lwd=2)
> legend("topright", legend=c("Droidi", "Gungan", "Human", "Kaminoan",
+ "Mirialan", "Twi'lek", "Wookiee", "Zabrak"),
+ col=c("red", "blue", "green", "yellow",
+ "orange", "purple", "brown", "pink"), lwd=2)
Alternativno, možda želimo dobiti uvid u distribuciju podataka o opaženim visinama (a ne generiranim vrijednostima) koristeći box-plot. Ako kreiramo usporedne box-plotove za sve vrste iz podskupa filtered_data, moći ćemo ih međusobno usporediti.
> ggplot(filtered_data, aes(x = vrsta, y = visina, fill = vrsta)) +
+ geom_boxplot(alpha = 0.7) +
+ labs(
+ title = "Box-plot visina po vrstama",
+ x = "Vrsta",
+ y = "Visina"
+ ) +
+ theme_minimal() +
+ theme(
+ plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
+ axis.text.x = element_text(angle = 45, hjust = 1)
+ ) +
+ scale_fill_brewer(palette = "Set3")
Box-plot prikazuje značajne razlike u visinama među vrstama. Kaminoan i Wookiee ističu se kao najviše vrste, s visokim vrijednostima medijana, dok Droidi i Mirialan imaju najniže medijane. Raspon visina je najširi kod Droida, što sugerira veliku varijabilnost unutar te vrste, dok vrste poput Wookiee i Zabrak imaju uže raspone, što znači da su visine unutar tih vrsta konzistentnije. Human i Gungan imaju slične raspone varijacija.
Neke vrste, poput Kaminoan, nemaju izdvojenice, dok druge vrste pokazuju visine koje su izvan tipičnih vrijednosti. Ova usporedba omogućuje bolji uvid u razlike među vrstama, naglašavajući kako se vrste razlikuju ne samo po prosječnoj visini već i po varijabilnosti i ekstremnim vrijednostima unutar svojih distribucija.
No, za pokazatelje deskriptivne statistike, možemo, na primjer, koristiti i paket summarytools. S obzirom da želimo izračunati pokazatelje za svaku vrstu zasebno, kombinirat ćemo s naredbom stby()
iz paketa dplyr. Prva naredba, kojom bismo utvrdili sve vrste, neće se pokrenuti, jer je ispis podugačak. No, možete isprobati sami. Drugom skupinom naredbi kreira se podskup podataka koji obuhvaća dvije vrsta (Droide i ljude), a potom se izračunavaju pokazatelji deskriptivne statistike za svaku vrstu likova.
> # stby(data = Starwars, INDICES = Starwars$vrsta,
> # FUN = function(x) descr(Starwars[,2:3], stats = "all"))
> starwars_subset <- Starwars %>%
+ filter(Starwars$vrsta %in% c("Human", "Droid"))
>
> stby(data = starwars_subset[, c("tezina", "visina")],
+ INDICES = starwars_subset$vrsta,
+ FUN = descr,
+ stats = "all")
## Descriptive Statistics
##
## tezina visina
## ----------------- -------- --------
## Mean 69.75 131.20
## Std.Dev 51.03 49.15
## Min 32.00 96.00
## Q1 32.00 96.00
## Median 53.50 97.00
## Q3 107.50 167.00
## Max 140.00 200.00
## MAD 31.88 1.48
## IQR 59.25 71.00
## CV 0.73 0.37
## Skewness 0.45 0.41
## SE.Skewness 1.01 0.91
## Kurtosis -1.95 -2.02
## N.Valid 4.00 5.00
## Pct.Valid 66.67 83.33
##
## N: 38
##
## tezina visina
## ----------------- -------- --------
## Mean 82.78 177.64
## Std.Dev 19.38 12.12
## Min 45.00 150.00
## Q1 77.00 170.00
## Median 79.00 180.00
## Q3 84.00 185.00
## Max 136.00 202.00
## MAD 5.93 11.86
## IQR 7.00 15.00
## CV 0.23 0.07
## Skewness 0.80 -0.54
## SE.Skewness 0.49 0.41
## Kurtosis 1.46 -0.17
## N.Valid 22.00 33.00
## Pct.Valid 57.89 86.84
Droidi su prosječno teški 69.75 kg, uz standardno odstupanje težina od prosjeka za 51.03 kg ukazuje na relativno veliku varijabilnost. U malim uzorcima uobičajeno se opaža veća varijabilnost u podacima. Raspon težina, od 32 kg do 140 kg, dodatno potvrđuje postojanje ekstremnih vrijednosti. Polovica Droida u uzorku teška je 53 kg ili manje od toga, dok je preostala polovica teška toliko ili više. Središnjih 50% podataka o visini nalazi se između 55 i 85 kg. Distribucija težine Droida blago je pozitivno asimetrična, dok je distribucija vrhom zaobljenija od normalne.
Droidi su prosječno visoki 131.20 cm, uz standardno odstupanje visine od prosjeka za 49.15 cm. Raspon varijacija visina kreće se od 96 do 200 cm. Središnjih 50% Droida visoko je između 96 i 167 cm, ukazujući na izdvojenice s desne strane distribucije. To potvrđuje i pokazatelj asimetrije, ukazujući na to da je distribucija visina Droida blago pozitivno asimetrična. Slično kao i distribucija težina, distribucija visina Droida je vrhom zaobljenija od normalne.
Ljudi u uzorku su prosječno teški 82.78 kg, uz standardno odstupanje težine od prosjeka za 19.38 kg, što ukazuje na umjerenu varijabilnost težina među ljudima. Polovica ljudi u uzorku ima težinu od 79 kg ili manje, dok druga polovica ima težinu veću od toga. Prosjek je veći od medijana, što upućuje na postojanje nekolicine velikih vrijednosti u nizu, koje odvlače prosjek k većim vrijednostima. Raspon težina kreće se od minimalnih 45 kg do maksimalnih 136 kg, dok se središnjih 50% podataka o težini nalazi u intervalu između 77 kg i 84 kg. Distribucija težine je blago pozitivno asimetrična, što potvrđuje da postoji nekoliko ljudi s većim težinama koje odstupaju od većine opažanja. Kurtosis, ili zaobljenost distribucije, ukazuje na izduženiji vrh distribucije u odnosu na normalnu i veću koncentraciju opažanja oko prosjeka.
Prosječna visina ljudi u uzorku iznosi 177.64 cm, uz standardno odstupanje od 12.12 cm, što ukazuje na nisku varijabilnost visina. Raspon visina kreće se od minimalnih 150 cm do maksimalnih 202 cm. Središnjih 50% ljudi visoko je između 170 cm i 185 cm. Distribucija visina je blago negativno asimetrična, što znači da postoji nekoliko ljudi s nižim visinama koje povlače distribuciju ulijevo. Kurtosis ukazuje na distribuciju koja je oblikom blizu normalnoj distribuciji, s blago zaobljenijim vrhom.
No, može nas zanimati i postoji li veza između visina i težina likova Starwarsa.
> starwars_clean <- Starwars %>%
+ select(vrsta, tezina, visina) %>%
+ filter(!is.na(visina) & !is.na(tezina))
>
> cor(starwars_clean[2:3], use = "pairwise.complete.obs")
## tezina visina
## tezina 1.00 0.13
## visina 0.13 1.00
Vrijednost korelacije 0.13 sugerira da postoji vrlo slab pozitivan odnos između težine i visine. To znači da, u prosjeku, s povećanjem visine, težina blago raste. Ipak, radi se o vrlo slaboj povezanosti, koja ne ukazuje na izraženu pravilnost.
Budući da skup podataka sadrži različite vrste likova, moguće je da razlike između skupina značajno smanjuju ukupnu korelaciju. Na primjer, Droidi mogu imati različite obrasce povezanosti težine i visine u usporedbi s ljudima. Bilo bi korisno izračunati korelacije unutar specifičnih skupina (npr. za ljude i Droide) kako bismo vidjeli postoji li jača povezanost u homogenijim podskupinama.
> library(ggplot2)
>
> ggplot(data = starwars_subset, aes(x = visina, y = tezina, color = vrsta)) +
+ geom_point(size = 3, alpha = 0.7) +
+ labs(
+ x = "Visina (cm)",
+ y = "Težina (kg)",
+ color = "Vrsta"
+ ) +
+ theme_minimal() +
+ theme(
+ plot.title = element_text(hjust = 0.5, size = 14),
+ axis.title = element_text(size = 12),
+ legend.title = element_text(size = 12),
+ legend.text = element_text(size = 10)
+ )
> cor_droid <- starwars_subset %>%
+ filter(vrsta == "Droid") %>%
+ select(tezina, visina) %>%
+ cor(use = "pairwise.complete.obs")
> cor_droid
## tezina visina
## tezina 1.00 0.96
## visina 0.96 1.00
Koeficijent korelacije između težine i visine Droida iznosi 0.96, što ukazuje na vrlo snažnu pozitivnu linearnu vezu. To znači da, kako se povećava visina Droida, težina također gotovo proporcionalno raste. Ovaj visok koeficijent može biti posljedica malog uzorka Droida i homogennosti njihovih karakteristika u skupu podataka, ali je vjerojatnije da je težina rezultat njihove visine i materijala koji su korišteni u njihovoj konstrukciji (veći Droidi zahtijevaju više materijala, što povećava njihovu težinu). S obzirom da Droidi nemaju biološke varijacije poput ljudi (npr., razlike u masi mišića, gustoći kostiju ili postotku masti), veza između težine i visine je jača.
> cor_human <- starwars_subset %>%
+ filter(vrsta == "Human") %>%
+ select(tezina, visina) %>%
+ cor(use = "pairwise.complete.obs")
> cor_human
## tezina visina
## tezina 1.00 0.51
## visina 0.51 1.00
Koeficijent krelacije između težine i visine iznosi 0.51, što ukazuje na umjerenu pozitivnu linearnu vezu. Ovo je očekivano jer su kod ljudi visina i težina povezane, ali nisu savršeno proporcionalne (npr., razlike u građi tijela, masi mišića, itd.). Dakle umjerena pozitivna korelacija je u skladu s raznolikošću podataka o ljudima u uzorku.
Također, sličnu analizu možemo provesti i za sve vrste, no ovdje ćemo samo grafički prikazati uvide koje možemo dobiti dijagramom rasipanja.
> library(ggplot2)
> library(dplyr)
>
> starwars_clean <- Starwars %>%
+ # odabiremo opažanja koja ne sadrže NA
+ # te eliminiramo jednu izdvojenicu
+ filter(!is.na(visina) & !is.na(tezina) & tezina <= 1000) %>%
+ select(vrsta, visina, tezina)
>
> ggplot(data = starwars_clean, aes(x = visina, y = tezina, color = vrsta)) +
+ geom_point(size = 3, alpha = 0.7) +
+ labs(
+ title = "Raspršenost visine i težine u Starwars skupu podataka",
+ x = "Visina (cm)",
+ y = "Težina (kg)",
+ color = "Vrsta"
+ ) +
+ theme_minimal() +
+ theme(
+ plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
+ axis.title = element_text(size = 12),
+ legend.title = element_text(size = 12),
+ legend.text = element_text(size = 10),
+ legend.position = "bottom"
+ )
Ako želite, možete samostalno provesti daljnju analizu visina i težina za svaku vrstu, po uzoru na postupak proveden za Droide i ljude.
Sljedeće nas zanima koji likovi iz određenih vrsta imaju visinu i težinu iznad dvije standardne devijacije od prosjeka za svoju vrstu? Odgovor na to pitanje iziskuje nekoliko koraka u analizi. Prvo je potrebno izračunati prosječnu visinu i težinu za svaku vrstu u skupu podataka. Nakon toga trebamo filtrirati likove koji su iznad prosječne visine i težine za svoju vrstu. I naravno, na kraju treba ispisati ili prikazati rezultate. Ovo je izvrstan primjer na kojem se može prikazati kreiranje vlastitih funkcija u kontekstu analize podataka.
> library(dplyr)
>
> # Funkcija za pronalazak likova iznad prosječne visine i težine
> iznadprosjecni_likovi <- function(data, vrsta, visina, tezina) {
+
+ # 1. Grupiranje podataka po vrsti i računanje prosjeka
+ avg_stats <- data %>%
+ group_by(!!sym(vrsta)) %>%
+ summarize(
+ avg_visina = mean(!!sym(visina), na.rm = TRUE),
+ sd_visina = sd(!!sym(visina), na.rm = TRUE),
+ avg_tezina = mean(!!sym(tezina), na.rm = TRUE),
+ sd_tezina = sd(!!sym(tezina), na.rm = TRUE)
+ )
+
+ # 2. Spajanje originalnih podataka s prosjecima
+ data_with_avg <- data %>%
+ left_join(avg_stats, by = vrsta)
+
+ # 3. Filtriranje likova čija visina i težina odstupaju više od 2 standardne devijacije iznad prosjeka
+ above_2sd <- data_with_avg %>%
+ filter(
+ !!sym(visina) > avg_visina + 2 * sd_visina &
+ !!sym(tezina) > avg_tezina + 2 * sd_tezina
+ ) %>%
+ select(ime, !!sym(vrsta), !!sym(visina), !!sym(tezina))
+
+ return(above_2sd)
+ }
>
> # Primjena funkcije
> likovi <- iznadprosjecni_likovi(
+ data = Starwars,
+ vrsta = "vrsta",
+ visina = "visina",
+ tezina = "tezina"
+ )
>
> # Prikaz rezultata
> likovi
## ime vrsta visina tezina
## 1 Darth Vader Human 202 136
Recimo da se sad želimo usredotočiti na raznovrsnost imena i želimo ih prvo poredati po abecedi. Jedan od načina kako možemo dobiti takav prikaz i čitav skup podataka poredati prema imenima likova je koristeći funkciju arrange()
.
> sorted_Starwars <- arrange(Starwars, ime)
> # kad bismo htjeli poredati silazno po imenima Z->A,
> # onda bi umjesto imena upisali desc(ime)
> str(sorted_Starwars)
## 'data.frame': 87 obs. of 7 variables:
## $ ime : chr "Ackbar" "Adi Gallia" "Anakin Skywalker" "Arvel Crynyd" ...
## $ visina : int 180 184 188 NA 178 NA 191 166 163 165 ...
## $ tezina : num 83 50 84 NA 55 NA NA 50 65 75 ...
## $ boja_kose : chr "unknown" "unknown" "blonde" "brown" ...
## $ boja_ociju: chr "orange" "blue" "blue" "brown" ...
## $ planet : chr "Mon Cala" "Coruscant" "Tatooine" NA ...
## $ vrsta : chr "Mon Calamari" "Tholothian" "Human" "Human" ...
Ako nas zanima koliko je jedinstvenih imena, odnosno likova, obuhvaćeno ovim skupom podataka, možemo koristiti funkciju unique()
.
> unique(sorted_Starwars$ime)
## [1] "Ackbar" "Adi Gallia" "Anakin Skywalker"
## [4] "Arvel Crynyd" "Ayla Secura" "BB8"
## [7] "Bail Prestor Organa" "Barriss Offee" "Ben Quadinaros"
## [10] "Beru Whitesun Lars" "Bib Fortuna" "Biggs Darklighter"
## [13] "Boba Fett" "Bossk" "C-3PO"
## [16] "Captain Phasma" "Chewbacca" "Cliegg Lars"
## [19] "Cord\xe9" "Darth Maul" "Darth Vader"
## [22] "Dexter Jettster" "Dooku" "Dorm\xe9"
## [25] "Dud Bolt" "Eeth Koth" "Finis Valorum"
## [28] "Finn" "Gasgano" "Greedo"
## [31] "Gregar Typho" "Grievous" "Han Solo"
## [34] "IG-88" "Jabba Desilijic Tiure" "Jango Fett"
## [37] "Jar Jar Binks" "Jek Tono Porkins" "Jocasta Nu"
## [40] "Ki-Adi-Mundi" "Kit Fisto" "Lama Su"
## [43] "Lando Calrissian" "Leia Organa" "Lobot"
## [46] "Luke Skywalker" "Luminara Unduli" "Mace Windu"
## [49] "Mas Amedda" "Mon Mothma" "Nien Nunb"
## [52] "Nute Gunray" "Obi-Wan Kenobi" "Owen Lars"
## [55] "Padm\xe9 Amidala" "Palpatine" "Plo Koon"
## [58] "Poe Dameron" "Poggle the Lesser" "Quarsh Panaka"
## [61] "Qui-Gon Jinn" "R2-D2" "R4-P17"
## [64] "R5-D4" "Ratts Tyerel" "Raymus Antilles"
## [67] "Rey" "Ric Oli\xe9" "Roos Tarpals"
## [70] "Rugor Nass" "Saesee Tiin" "San Hill"
## [73] "Sebulba" "Shaak Ti" "Shmi Skywalker"
## [76] "Sly Moore" "Tarfful" "Taun We"
## [79] "Tion Medon" "Wat Tambor" "Watto"
## [82] "Wedge Antilles" "Wicket Systri Warrick" "Wilhuff Tarkin"
## [85] "Yarael Poof" "Yoda" "Zam Wesell"
Recimo da nas u sljedećem koraku zanimaju boje kose prema vrsti likova te apsolutne frekvencije u kojima se pojedine kombinacije pojavljuju. Za to nam je potrebna tablica kontingence.
> contingency_table <- table(Starwars$boja_kose, Starwars$vrsta)
>
> # Prikazivanje tablice
> contingency_table
##
## Aleena Besalisk Cerean Chagrian Clawdite Droid Dug Ewok Geonosian
## auburn 0 0 0 0 0 0 0 0 0
## black 0 0 0 0 0 0 0 0 0
## blonde 0 0 0 0 1 0 0 0 0
## brown 0 0 0 0 0 0 0 1 0
## grey 0 0 0 0 0 0 0 0 0
## unknown 1 1 0 1 0 6 1 0 1
## white 0 0 1 0 0 0 0 0 0
##
## Gungan Human Hutt Iktotchi Kaleesh Kaminoan Kel Dor Mirialan
## auburn 0 3 0 0 0 0 0 0
## black 0 9 0 0 0 0 0 2
## blonde 0 3 0 0 0 0 0 0
## brown 0 16 0 0 0 0 0 0
## grey 0 1 0 0 0 0 0 0
## unknown 3 4 1 1 1 2 1 0
## white 0 2 0 0 0 0 0 0
##
## Mon Calamari Muun Nautolan Neimodian Pau'an Quermian Rodian Skakoan
## auburn 0 0 0 0 0 0 0 0
## black 0 0 0 0 0 0 0 0
## blonde 0 0 0 0 0 0 0 0
## brown 0 0 0 0 0 0 0 0
## grey 0 0 0 0 0 0 0 0
## unknown 1 1 1 1 1 1 1 1
## white 0 0 0 0 0 0 0 0
##
## Sullustan Tholothian Togruta Toong Toydarian Trandoshan Twi'lek
## auburn 0 0 0 0 0 0 0
## black 0 0 0 0 1 0 0
## blonde 0 0 0 0 0 0 0
## brown 0 0 0 0 0 0 0
## grey 0 0 0 0 0 0 0
## unknown 1 1 1 1 0 1 2
## white 0 0 0 0 0 0 0
##
## Umbaran Vulptereen Wookiee Xexto Yoda's species Zabrak
## auburn 0 0 0 0 0 0
## black 0 0 0 0 0 1
## blonde 0 0 0 0 0 0
## brown 0 0 2 0 0 0
## grey 0 0 0 0 0 0
## unknown 1 1 0 1 0 1
## white 0 0 0 0 1 0
S obzirom da postoji puno jedinstvenih kombinacija i jako puno kombinacija koje se ne pojavljuju, možemo isto ispitati za podskup vrsta za koje smo ranije utvrdili da su učestalije i spremili u df filtered_data.
> contingency_table <- table(filtered_data$boja_kose, filtered_data$vrsta)
>
> # Prikazivanje tablice
> contingency_table
##
## Droid Gungan Human Kaminoan Mirialan Twi'lek Wookiee Zabrak
## auburn 0 0 3 0 0 0 0 0
## black 0 0 9 0 2 0 0 1
## blonde 0 0 3 0 0 0 0 0
## brown 0 0 16 0 0 0 2 0
## grey 0 0 1 0 0 0 0 0
## unknown 6 3 4 2 0 2 0 1
## white 0 0 2 0 0 0 0 0
Svi Droidi imaju nepoznatu boju kose, odnosno nemaju kose. Slična je situacija i sa svim Gunganima, Kaminoanima, Twi’lekima i jednim/om Zabrakom. Kosa ljudi se pojavljuje u najviše boja. Temeljem ovog uzorka, moglo bi se zaključiti da Mirilalani imaju crnu kosu, Wookiee imaju smeđu kosu, a Zabraci imaju crnu ili nemaju kose.
Što bi nas moglo zanimati dalje? Moglo bi nas zanimati postoji li statistički značajna razlika u težinama s obzirom na vrstu. Mogli bismo htjeti kreirati dodatne grafičke prikaze… Uz dovoljno podataka i predznanja te malo znatiželje, dostupni skupovi podataka u R-u mogu postati nepresušna oaza za vježbanje i kalibriranje vještina upravljanja podacima.
Zadaci
Otvorite novi R Script dokument.
- Kreirajte vektor z koji će sadržavati sve parne brojeve između 50 i 100.
- Provjerite tip z-a.
- Izračunajte prosjek vrijednosti varijable z.
- Kreirajte podatkovni okvir prema podacima iz tablice na 32. stranici u Statističkim informacijama
- Pretvorite podatkovni okvir iz prošlog zadatka u tablicu.
- Kreirajte vektor temeljem podataka iz tablice na 33. stranici Statističkih informacija, na način da koristite samo opažanja iz 2020. godine za minimalno šest varijabli.
- Kreirajte vektor temeljem podataka iz tablice na 33. stranici Statističkih informacija, na način da koristite samo opažanja iz 2019. godine za iste varijable koje ste odabrali u prethodnom zadatku.
- Vektorima iz 6. i 7. zadatka pridružite nazive.
- Spojite vektore iz 6. i 7. zadatka.
- Vektor iz prethodnog zadatka pretvorite u matricu.
- Matrici iz prethodnog zadatka pridodajte opažanja iz 2018., za iste varijable, iz istog izvora podataka.
- Matricu pretvorite u podatkovni okvir.
- Iz podatkovnog okvira obrišite jedan podatak iz 2018. godine.
- Iz podatkovnog okvira obrišite jednu, proizvoljno odabranu, varijablu.
- Izračunajte nekoliko statističkih pokazatelja za preostale varijable.
- Je li moguće spojiti dva podatkovna okvira koja ste kreirali? Obrazložite odgovor.
- Ako vas zanima udio nezaposlenih žena prema razinama obrazovanja, na koji način možete sortirati/filtrirati podatkovni okvir?
- Na stranici 36. Statističkih informacija pogledajte dio podataka pod nazivom Upisani studenti. Na koje je sve načine moguće podatke zapisati u R-u? O kakvim se podacima radi? Što su opažanja, a što su varijable?
- Na stranici 53 istog dokumenta, nalazi se tablica „BRUTO DOMAĆI PROIZVOD REPUBLIKE HRVATSKE”. Razmislite o kakvim se podacima radi, što su varijable, a što opažanja i na koji bi način bilo potrebno upisati podatke u R da se kreira podatkovni okvir.
- Ako niste ranije, bilo bi dobro sad proći sve primjere naredbi u ovom dokumentu. Osobitu pozornost posvetite onim funkcijama koje su vam nejasne i ne zaboravite koristiti prozor Help. Ako i nakon toga imate poteškoće, javite se za konzultacije ili pitajte na početku sljedećeg sata.
Otvorite novi R Script dokument.
- Iz paketa nycflights13 uvezite podatke flights.
- Izdvojite sve letove koji su poletjeli iz zračne luke JFK i imali kašnjenje pri polasku veće od 60 minuta.
- Sortirajte letove prema duljini leta (air_time) u silaznom redoslijedu.
- Dodajte novu varijablu koja prikazuje razliku između planiranog i stvarnog vremena dolaska (arr_delay - dep_delay).
- Kreirajte novi podatkovni okvir koji uključuje samo varijable origin, dest, air_time, i distance.
- Koliko je ukupno letova bilo iz svake zračne luke (origin)?
- Koji je bio najdulji let (air_time) iz zračne luke EWR?
- Kolika je prosječna udaljenost (distance) letova s obzirom na polazište (origin)?
- Kreirajte histogram koji prikazuje distribuciju kašnjenja pri polasku (dep_delay).
- Izračunajte pokazatelje deskriptivne statistike za varijable air_time i distance.
Otvorite novi R Script dokument.
- Učitajte podatke dostupne na: “http://sites.williams.edu/rdeveaux/files/2014/09/Saratoga.txt”
- Jesu li cijene kuća uz obalu (
Waterfront == 1
) više u usporedbi s onima koje nisu uz obalu? Odgovor potkrijepite grafički. - Kako se cijene nekretnina mijenjaju s obzirom na broj soba (Rooms)?
- Jesu li cijene novoizgrađene nekretnine (
New.Construct == 1
) više u odnosu na one koje nisu novogradnja? - Imaju li kuće s više kamina (Fireplaces) veću prosječnu cijenu? Kako se cijena razlikuje za kuće s jednim, dva ili više kamina?
- Kako je omjer broja kupaonica (Bathrooms) i broja soba (Rooms) vezan uz cijenu kuće? Jesu li kuće s većim brojem kupaonica po sobi skuplje?
- Izračunajte pokazatelje deskriptivne statistike za sve kvantitativne varijable.
- Kreirajte prikladan grafički prikaz za svaku varijablu u ovom podatkovnom okviru.
- Korištenjem grafičkog prikaza provjerite razlike u medijalnim cijenama kuća s obzirom na centralno grijanje (Central.Air)?
- Kreirajte tablice frekvencija za sve kvalitativne varijable o ovom skupu podataka.
Otvorite novi R Script dokument.
- U svibnju 2024., više od 65000 programera odgovorilo je na godišnju anketu o kodiranju, tehnologijama i alatima koje koriste i koje žele naučiti, umjetnoj inteligenciji i iskustvu programera na poslu. Podaci su dostupni za preuzimanje putem linka u .zip datoteci. Ta datoteka uključuje provedeni upitnik (u pdf formatu) te dva .csv dokumenta. Učitajte survey_results_public.csv.
- Izračunajte udio vrijednosti koje nedostaju za svaku varijablu. Je li možda samo pitanje razlog izostanka odgovora?
- Pronađite 10 najčešćih zemalja (Country) među ispitanicima i izračunajte njihovu relativnu učestalost.
- Kreirajte tablicu frekvencija za starosne skupine (Age) i prikažite podatke grafički.
- Kreirajte tablicu kontingence za varijable Employment i LearnCode.
- Izdvojite jedinstvene vrijednosti za sve OfficeStackAsync te sve OfficeStackSync varijable, a nakon toga utvrdite učestalosti. Koje su najpoželjnije baze?
- Izdvojite najčešće jezike koje ispitanici koriste (LanguageHaveWorkedWith) i prikažite njihove frekvencije.Koristeći tablicu kontingencije, povežite s načinom na koji su naučili kodirati (LearnCode)
- Izdvojite sve varijable koje sadrže Admired u nazivu i utvrdite učestalosti svakog modaliteta.
- Izdvojite i grafički prikažite najčešće načine upotrebe AI-a.
- Zadovoljstvo poslom mjereno je varijablama koje u nazivu sadrže JobSatPoints. Kreirajte novu varijablu, na način da ona predstavlja niz prosječnih opažanja po recima, a nakon toga, tu novu varijablu prikažite histogramom i box-plotom.
- Pronađite jezike koje ispitanici žele koristiti (LanguageWantToWorkWith) i usporedite s jezicima koje trenutno koriste.
- Izračunajte osnovne statističke pokazatelje za godišnje plaće (ConvertedCompYearly), uklanjajući vrijednosti koje nedostaju.
- Prikažite distribuciju veličina organizacija (OrgSize) u kojima ispitanici rade.
- Izračunajte prosječno radno iskustvo u godinama (WorkExp) za ispitanike koji rade puno radno vrijeme.
- Postoji li veza između radnog iskustva u godinama (WorkExp) i godišnjih plaća (ConvertedCompYearly) zaposlenika? Je li ta veza jača ili slabija, ako se odnos tih varijabli ispituje zasebno za ispitanike po državama?
Važno je ne zaboraviti - na kraju rada pohraniti projekt/ skriptu…