# ------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------- # Osa 1 - esmane kirjeldav statistika tudengite andmestiku alusel # ------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------- # Avage antud tekstifail R-i skriptina (R: Fail -> Open Script ...) # Kasutades vajadusel lisamaterjale # näiteks http://www.ms.ut.ee/mart/biomeetria2010/praks1.pdf # laske R-l täita alljärgnevad käsud (Ctrl+R käivitamaks parajasti aktiivset rida või selekteeritud osa) # ja püüdke aru saada, mida need teevad, vajadusel kirjutage enese tarvis juurde kommentaare # (märgi '#' järele kirjutatut tõlgendab R kommentaarina). # ------------------------------------------------------------------------------------- # Salvestage kursuse kodulehelt omale arvutisse andmestik studentsR.xls (http://ph.emu.ee/~ktanel/DK_0007/studentsR.xls) # ja avage see MS Excelis. # Andmestik sisaldab juhuslikku valikut (n = 100) esimese kursuse veterinaarmeditsiini- ja loomakasvatuse eriala tudengite # ankeedivastustest aastaist 2003-2005. # R-i importimiseks salvestage see tudengite andmetabel csv-failina # NB! csv-failina tuleb salvestada üksnes algandmeid sisaldav lehekülg!! # Püüa salvestatud fail käsu read.csv abil R-i importida andes ette faili täpse aadressi ja # määrates ära veergude ja kümnendkohtade eraldajana kasutatud sümbolid # (selguse mõttes võid csv-faili avada enne ka Notepadis ja vaadata need eraldajad järgi) # Käsk ise on järgmine: students=read.csv("C:/Documents and Settings/Tanel/My Documents/DK_0007/studentsR.csv",header=TRUE,sep=";",dec=",") # Probleemide korral võite andmestiku sisse lugeda ka internetist: students=read.csv("http://www.eau.ee/~ktanel/DK_0007/studentsR.csv",header=TRUE,sep=";",dec=",") # Veel on variant importida andmestik Excelist arvuti vahemällu (clipboardi) kopeerituna. # See tähendab, et võtate Excelis andmetabeli plokki, vajutate 'Ctrl'+'C' ning rakendate seejärel R-s järgnevat käsku tudengid <- read.table("clipboard", header=TRUE, sep="\t", dec=".", na.strings="") # Esmane ülevaade andmetabelist summary(tudengid) names(tudengid) head(tudengid) # Järgnev käsk teeb vaikimisi kasutatavaks andmestiku "students" # Miks seda vaja on? attach(students) # ------------------------------------------------------------------------------------- mean(pikkus) mean(pikkus[sugu=="N"]) by(pikkus,sugu,mean) tapply(pikkus,sugu,mean) summary(pikkus) # veel funktsioone: length, min, max, range, median, sd, var, quantile(pikkus, 0.13) mean(kaal) # Probleem selles, et R on pedantne puuduvate väärtuste osas # - talle tuleb eraldi öelda, mida nendega teha - näiteks eemaldada analüüsist: mean(kaal,na.rm=T) # not available remove = true mean(kaal[sugu=="N" & bmi>mean(bmi,na.rm=T)], na.rm=T) mean(na.omit(kaal)) # pisut universaalsem puuduvate väärtuste kõrvale jätmise variant mean(na.omit(kaal[sugu=="N" & mat>3])) sum(!is.na(kaal)) length(na.omit(kaal)) # ------------------------------------------------------------------------------------- # Proovi ise (selle praktikumi nö ise tegemise ülesanded moodustavad kokku esimese iseseisva töö): # ----------- # Leia keskmine ja mediaan tunnusele peaümbermõõt sõltuvalt matemaatika hindest. # Kas mannaputru söövate tudengite kehakaalude varieeruvus on suurem, kui mannaputru mitte söövatel tudengitel? # ------------------------------------------------------------------------------------- table(X6nnelik) barplot(table(X6nnelik), main="Õnnelikkuse esinemissagedus",ylab="Tudengite arv",xlab="Õnnelik?",col=heat.colors(3)) barplot(table(mannap), col=c("yellow","orange","red"), ylim=c(0,50)) # Vaikimisi kirjutab R vana joonise uue joonisega üle, aga # soovi korral võib lasta R-l ka tehtud jooniseid säilitada # - selleks tuleb joonise aktiivne olekul valida menüüst History -> Recording # peale paljude jooniste tegemist saab neid vaadata PageUp & PageDown klahvide abil # ------------------------------------------------------------------------------------- table(ainegr) # Probleem - R tõlgendab antul juhul tühja lahtrit reaalse väärtusena, # korrektsete analüüside tarvis tuleks R-le öelda, et tühja lahtri näol om tegu puuduva väärtusega # Viimase tarvis tuleks andmestikku lisada uus ja korrektne tuunus detach(students) # andestikule uue tunnuse lisamiseks tuleb andmestik esmalt deaktiveerida ... students$ainegr2=ifelse(students$ainegr!="O",ifelse(students$ainegr!="S",ifelse(students$ainegr!="A",NA,students$ainegr),students$ainegr),students$ainegr) table(students$ainegr2) attach(students) table(factor(ainegr2,labels=c("Art","Other","Science"))) ainegrf=factor(ainegr2,labels=c("Art","Other","Science")) round(100*prop.table(table(ainegrf)),2) pie(table(ainegrf)) # Mis on vahet järgneval kahel tabelil? 100*prop.table(table(sugu,ainegrf),1) round(100*prop.table(table(sugu,ainegrf),2),1) addmargins(table(sugu,ainegrf)) # ------------------------------------------------------------------------------------- # Proovi ise: # ----------- # Kuidas tudengid jaotuvad matemaatika hinde lõikes - tee sagedustabel ja tulpdiagramm. # Kas erialati on matemaatika hinnete suhtelised sagedused erinevad? # Konstrueeri sektordiagramm tunnusele sugu ja lase R-l juurde kirjutada "naised" ja "mehed". # ------------------------------------------------------------------------------------- hist(kaal,col="red",las=1) hist(kaal,col="gold",las=1,ylab="f(x)",xlab="x",main="Kaalu tihedus",xlim=c(30,110),probability=TRUE) lines(density(na.omit(kaal)),lwd=2) # Järgnevad 4 rida võid ka korraga käivitada par(mfrow=c(2,1)) # jagab joonise akna 2-ks reaks ja 1-ks veeruks hist(kaal[sugu=="N"],xlim=c(40,100), main="Naised", xlab="kaal(kg)", ylab="Sagedus") hist(kaal[sugu=="M"],xlim=c(40,100), main="Mehed", xlab="kaal(kg)", ylab="Sagedus") par(mfrow=c(1,1)) # Soovi korral võib intervallid ka ise moodustada: kaaluvahemik=cut(kaal,c(40,50,60,70,80,90,100)) # täpsete intervallipiiride asemel võib R-le ka lihtsalt öelda, kui mitut intervalli soovite: ...cut(weight,6) table(kaaluvahemik) 100*prop.table(table(kaaluvahemik)) table(kaaluvahemik,sugu) Mehed=table(kaaluvahemik[sugu=="M"]) Naised=table(kaaluvahemik[sugu=="N"]) barplot(rbind(Naised,Mehed),beside=TRUE,legend.text=TRUE,col=c("Green2","Green4")) boxplot(pikkus, ylim=c(150,195)) boxplot(pikkus~factor(sugu), col="skyblue1", names=c("Mehed","Naised"), ylim=c(150,195), main="Karp-vurrud-daigramm pikkusele") # Veel keerulisemad joonised (käivita järgmised 8 käsurida korraga): par(mfrow=c(2,1)) hist(pikkus[sugu=="M"], col="lightblue", main="Mehed", ylab="Osakaal", xlab="Pikkus", las=1, probability=TRUE, ylim=c(0,0.065), xlim=c(150,205)) lines(density(na.omit(pikkus[sugu=="M"]))) hist(pikkus[sugu=="N"], col="red", main="Naised", ylab="Osakaal", xlab="Pikkus", las=1, probability=TRUE, ylim=c(0,0.065), xlim=c(150,205)) lines(density(na.omit(pikkus[sugu=="N"])), lty=2) par(mfrow=c(1,1)) # ------------------------------------------------------------------------------------- # Proovi ise: # ----------- # Joonsta mannaputru söövate ja mittesöövate tudengite kehakaalude histogrammid ja tihedusfunktsioonid. # Konstrueeri sagedustabel tunnusele pikkus, jagades pikkused 6 klassi # Konstrueeri karp-vurrud diagrammid tunnusele peaümbermõõt sõltuvalt matemaatika hindest # ------------------------------------------------------------------------------------- # Mitmesugused testid (püüa sõnastada järeldused kõigi testide tulemuste alusel) # Kas tudengite keskmine pikkus erineb 170-st? t.test(pikkus,mu=170,conf.level=0.99) t.test(pikkus[sugu=="M"],mu=180,conf.level=0.95) # Kas matemaatikas 3- ja 4-liste keskmised peaümbermõõdud on erinevad? t.test(peaymb[mat==3],peaymb[mat==4]) # eeldab normaaljaotust mõlemas võrreldavas grupis # ei eelda normaaljaotust wilcox.test(peaymb[mat==3],peaymb[mat==4]) # Wilcoxoni ehk Mann-Whitney test ks.test(peaymb[mat==3],peaymb[mat==4]) # Kolmogorov-Smirnovi test # Hoiatus tähendab, et andmestikus esineb korduvaid väärtusi, KS-test aga eeldab vaikimis, et korduvad väärtused puuduvad # Kas peaümbermõõtude varieeruvus sõltub soost? bartlett.test(peaymb, sugu) # Bartlett' test - dispersioonide võrdlemisel kasutatava F-testi edasiarendus # (eeldab, et uuritava tunnuse jaotus kõigis võrreldavais gruppides on normaaljaotus) # Kui normaaljaotust pole, siis on dispersioonide võrdlemisel kasutatav Fligner-Killeen'i test: fligner.test(peaymb, sugu) # Kas tudengite peaümbermõõt erineb normaaljaotusest? shapiro.test(peaymb) # Shapiro-Wilk'i test # Nagu enamus normaaljaotust kontrollivaid teste, on ka SW'i test enamasti liiga range # ja praktilistes analüüsides piisab normaaljaotuse graafilisest kontrollimisest. Näiteks: hist(peaymb) # Et gruppide võrdlemisel eeldatakse normaaljaotust igas grupis, siis ... (käivitage 4 järgmist rida korraga): par(mfrow=c(2,2)) by(peaymb, sugu, hist) by(peaymb, sugu, qqnorm) par(mfrow=c(1,1)) # Juhul, kui puuduvaid väärtuseid ei ole, sobib normaaljaotuse testimiseks ka Kolmogorov-Smirnovi test: ks.test(pikkus, pnorm, mean=mean(pikkus), sd=sd(pikkus)) # ------------------------------------------------------------------------------------- # Proovi ise: # ----------- # Leidke naistudengite keskmise kaalu 95%-usalduspiirid. Kas naistudengite keskmine kaal erineb statistiliselt oluliselt 60 kg-st? # Kas nais- ja meestudengite keskmised kehamassiindeksid on statistiliselt oluliselt erinevad? # Kas tudengite kehamassiindeksite jaotus erineb normaaljaotusest? # ------------------------------------------------------------------------------------- # Lõpetuseks oleks soovitav aktiivne andmestik deaktiveerida: detach(students) # ------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------- # Osa 2 - andmete lisamine, andmetabelite ühendamine jm andmete haldamisega seonduv # ------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------- # Andmete tekitamine naide1 <- data.frame(c("Mari","Mari","Jüri","Mati","Mati","Mati","Siim","Siim"), c("A","B","C","B","C","A","A","A")) names(naide1) <- c("nimi","hinne") # loodud andmetabeli veergudele nimede andminenaide1 naide1 naide2 <- data.frame(c("Jüri","Mari","Mati","Siim"), c("I","I","II","III"), c("Loru","Usin","Rumal, aga edasipüüdlik","Oivik")) names(naide2) <- c("nimi","kursus","hinnang") naide2 # fix(naide2) # andmetabeli vaatamiseks ja soovi korral ka muutmiseks # Andmetabelite ühendamine # ------------------------------------------------------------------------------------- # Uu(t)e veer(g)u(de) lisamine (eeldus: ühendatavates tabelites on ühepalju ridu ja need read on samas järjekorras - enamasti see nii ei ole!) synniaasta <- c(1998, 1997, 1995, 1995) synnikuu <- c(1,5,12,9) synnipaev <- c(21,30,5,9) naide2 <- cbind(naide2, synniaasta, synnikuu, synnipaev) naide2 # Uu(t)e rea(ridade) lisamine (eeldus: ühendatavates tabelites on samapalju veerge ja need veerud on samas järjekorras) # Lisaks, lisatavad read peavad olema data.frame tüüpi ja samade nimedega! Paul <- data.frame("Paul","III","Loru",1992,10,1) names(Paul) <- names(naide2) (naide2 <- rbind(naide2, Paul)) # välimised sulud sunnivad R-i omistamistehte tulemuse ka välja trükkima Tiiu <- data.frame("Tiiu","D") names(Tiiu) <- names(naide1) (naide1 <- rbind(naide1, Tiiu)) # Soovides ühendada mitte samas järjekorras ridadega või osaliselt üldse mitte samu ridu sisaldavaid andmetabeleid, tuleks kasutada funktsiooni merge() # Mis on kahe järgneva käsu tulemustes erinevat? merge(naide2, naide1) (naide12 <- merge(naide1, naide2, all.x=TRUE, all.y=TRUE)) # Kui soovite eksportida andmetabelit R-st Excelisse, on sageli kiireim viis kasutada jällegi arvuti vahemälu. # Nimelt kirjutate esmalt järgneva käsuga soovitud andmestiku arvuti vahemällu (clipboardi) ja vajutate seejärel Excelis 'Ctrl'+'V' (ehk 'Paste') write.table(naide12, "clipboard") # Andmete sorteerimine # ------------------------------------------------------------------------------------- naide12 <- naide12[order(naide12$nimi), ] # esmalt sorteerime andmestiku kasvavalt nime ja selle siseselt hinde järgi View(naide12) # Et R-i andmete sorteerimise loogikast aru saada, vaadake, mida teeb käsk order(naide12$nimi, naide12$hinne) # Faktorite tasemete järjekorra muutmine # ------------------------------------------------------------------------------------- # Mis tüüpi on tunnused andmetabelis? str(naide12) # Vaimikisi järjestab R faktorite tasemed tähestikujärjekorras, näiteks tunnuse 'hinnang' tasemed järjestuses levels(naide12$hinnang) barplot(table(naide12$hinnang)) # Soovides tasemete järjekorda muuta, tuleb rakendada käsku factor() lisaargumendiga 'levels', kus on ära toodud soovitav tasemete järjekord # Lisaargument 'ordered=TRUE' tekitab faktori tasemete vahele järjestuse ...<...<... (NB! See ei ole sama asi, mis tasemete järjekord.) naide12$hinnang <- factor(naide12$hinnang, levels=c("Oivik","Usin","Rumal, aga edasipüüdlik","Loru"), ordered=TRUE) naide12$hinnang <- factor(naide12$hinnang, levels=c("Oivik","Usin","Rumal, aga edasipüüdlik","Loru")) naide12$hinnang < "Usin" # Lisaks võib käsu factor() argumendiga 'labels' faktori tasemeid ümber nimetada naide12$kursus <- factor(naide12$kursus, labels=c("Esimene","Teine","Kolmas")) naide12 # ümberjärjestatud ja -nimetatud faktorite tasemetega andmestik naide12$factor.SA <- factor(naide12$synniaasta) # Erinevate väärtuste arv # ------------------------------------------------------------------------------------- unique(naide12$nimi) # erinevate nimede list length(unique(naide12$nimi)) # erinevate nimede arv # Uute tunnuste väärtuste arvutamine # ------------------------------------------------------------------------------------- naide12$vanus <- 2018-naide12$synniaasta naide12$hinnang2 <- ifelse((naide12$hinnang=="Oivik")|(naide12$hinnang=="Usin"),"Positiivne","Negatiivne") # sümbol '|' tähendab 'või' naide12$nimi_kursus <- paste(naide12$nimi, naide12$kursus, sep="_") naide12$vanusegrupp <- cut(x=naide12$vanus, breaks=c(0,20,25,Inf), labels=c("<=20", "21-25", ">25")) # Alamandmestik # ------------------------------------------------------------------------------------- # Andmetabelist teatud tingimustele vastavat alamandmestikku on lihtsaim moodustada käsuga subset() (naide12a <- subset(naide12, subset=(naide12$kursus!="Kolmas")|(naide12$synniaasta>=1995))) # sümbol '|' tähendab 'või' (naide12b <- subset(naide12, subset=(naide12$kursus!="Kolmas")&(naide12$synniaasta>=1995))) # sümbol '&' tähendab 'ja' str(naide12b) # mis tüüpi on tunnused andmebaasis 'naide12b' # NB! Käsk subset() ei eemalda andmestikust enam mitte esinevaid faktori väärtuseid! Vt näiteks table(naide12b$nimi) # Lahenduseks on rakendada vastavale tunnusele uuesti funktsiooni factor() naide12b$nimi <- factor(naide12b$nimi) table(naide12b$nimi) # Kuupäevad (vt ka näiteks https://www.statmethods.net/input/dates.html) # ------------------------------------------------------------------------------------- # R-i ajaarvamine algab 1. jaanuarist 1970, st et kõik kuupäevad kujutavad enesest tegelikult päevade arvu 1. jaanuarist 1970 alates Sys.Date() # tänane kuupäev # Lisame andmebaasi sünniaja R-i vaikimisi kuupäeva vormingus yyyy-mm-dd naide12$synniaeg <- as.Date(paste(naide12$synniaasta,naide12$synnikuu,naide12$synnipaev,sep="-")) # Andmestiku vanima ja noorima isiku vanusevahe max(naide12$synniaeg, na.rm=T) - min(naide12$synniaeg, na.rm=T) as.numeric(naide12$synniaeg)