Az R statisztikai számításokra és adatok ábrázolásra létrehozott programnyelv. Teljes mértékben ingyenes és nyílt forráskódú, illetve egyaránt használható Unix/Linux, MS Windows és MacOS operációs rendszereken.
Ebben a notebookban a teljesség igénye nélkül betekintőt adunk az R használatáról. A notebook tartalmának megértéséhez szükséges, hogy a hallgatók tisztában legyenek az alapvető numerikus és statisztikai módszerekkel.
Hasznos linkek az R programozásról:
help(median)
?median
Az R-ben a külső csomagokat a library("csomag neve") parancs segítségével lehet betölteni:
library(base)
A kernel indításakor a base
nevű csomag automatikusan betöltésre kerül. Ebben a notebookban a base
csomag függvényeivel és adat struktúráival fogunk megismerkedni.
Segítség a csomagokról:
library(help = base)
Az R
-ben a számok alapműveletek és néhány előre definiált mathematikai konstans a python
-ban már megszokott módon működnek:
4+3
pi*100 # a pi itt is pi
5/7
3^2 # A hatvanyozas a ^-al történik!
Figylem a log
a természetes logaritmus! A log10
adja a 10-s alapú logaritmust.
log(exp(1))
Az értékadásra R
-ben a megszokott =
helyett a <-
konstrukció használandó!
a<- 13 # Így adunk értéket R-ben!!
a
print(a)
R-ben az =
szimbólumot, ahogy ez lenneb is látni fogjuk, fügvény argumentumok megadására használjuk.
A R
változók a python
-hoz hasonlóan több típusba sorolhatóak. Lehetnek numeric
(valós számok), logical
(bool típusú változók), integer
(egész számok), complex
(komplex számok), character
(betű illetve általánosabb karakter változók), list
(hasonlóan a python list-hez), ezeken kívül létezik a raw
ritkán használt változó típus is.
Az R
alapvető származtatott adatstruktúrája a vector. Vectorok definiálására a c()
függvényt célszerű használni:
vec <- c(1,2,3)
print(vec) # a vec változó kiiratása
Fontos az R-ben nem nullától indexelünk, hanem 1-től!
vec[0] # ez nem dob hibát de nem is tartalmaz semmit se!!
vec[1]
# ha integer-t szeretnénk, írjunk a szám után egy L betűt
egesz_szam <- 1L
egesz_szam
Az str() paranccsal megnézhetjük egy "objektum" minden tulajdonságát:
str(egesz_szam) # itt 1 darab int számról van csak szó
valos_szam <- 1
str(valos_szam) # A numeric változó valós számot jelent (pythonban ezek a float számok)
szavak <- c('cica', 'kutya', 'kigyó', 'alien', 'predator')
szavak
str(words)
A python
-os példákban láttuk hogy számtalanszor előfordul az, hogy egy probléma megoldása során szükségünk van számok sorozatainak előállítására. Erre R
-ben az alábbi "eleje:vege
" konstrucióval van lehetőség:
sor<- 100:90
sor
str(sor)
A python
dict-ek hez hasonó konstrukciót kapunk ha a vector elemeit nevekkel definiáljuk őket (python
dict-eknél kulcsoknak hívtuk ezeket a neveket ):
vec <- c(first = 1, second = 3, third = 6, fourth = 10)
vec
str(vec) # Itt megjelent az objektumok attribútom tulajdonásga, akit jobban érdekel nézzen utána
Ezen túl a nevekkel vagy a megfelelő index-el is hivatkozhatunk a megfelelő elemre:
vec[2]
vec['second']
A summary()
parancs összegzi a fontos tulajdonságokat a változóról (mint az átlag, szórás, ...). Nagy előnye a különbözö függványek kiértékelésekor lesz.
summary(vec)
summary(szavak)
Ha adott lépésközzel szeretnénk vektort létrehozni, akkor használjuk a seq()
parancsot:
seq(100,0,-5)
Az R vector objektumokból az alábbi bonyolultabb objektumok származnak:
Matrix-okat a matrix()
függvénnyel definiálunk:
mat <- matrix(1:8, nrow = 2, ncol = 4)
mat
A dim()
paranccsal megnézhető a dimneziója a mátrixnak:
dim(mat)
Vektorból is létrehozható:
newmat <- 3:6
dim(newmat) <- c(2, 2)
newmat
arr <- array(1:12, c(3, 2, 2)) # array-nel vektorral adjuk meg a dimenziokat
dim(arr)
mat <- matrix(1:8, 2, 4)
mat
Ha egy matrix dimenzióját megválltoztatjuk (ügyelve arra hogy az elemszám megmaradjon) akkor a matrixból array lesz:
arr <- mat
is.matrix(arr)
dim(arr) <- c(2, 2, 2) # átszabjuk a dimenziókat
is.matrix(arr) # az arr valtozó mar nem matrix!
is.array(arr) # hanem array
A factorok olyan vector-ok amelyeknek az elemei egy véges halamzból vesznek fel értékeket. Gondoljunk itt például egy osztály tanulóinak a nemére. Factorokat, nem túl meglepő módon a factor() segéd függvénnyel definiálhatunk:
fac <- factor(c("male", "male", "male", "female", "female", "male", "female"))
fac
A labels kulcsszóval felül definiálhatjuk az értékkészlet címkéit:
newfac<-factor(c(1,1,1,2,2,1,2), labels=c("male","female"))
newfac
A listák speciális vektor melyek vegyesen tartalmazhatnak különböző típusú elemeket (vektort, array-t, listát, stb.)
mylist <- vector("list", 2) # "ures"" lista letrehozasa
mylist
newlist <- list(a = 1, b = FALSE, letters[1:5]) # kozvetlen megadas
newlist
A data frame-ek speciális listák, amely azonos hosszúságú vektorokból állnak. A data frame-ek inspirálták a python
pandas
moduljának adatstruktúráját.
datfr <- data.frame(digits = 10:6, characters = letters[1:5])
datfr
Megkülönöztetjük a NA (not available) vagy a NaN (not a number) értékeket
Fontos: minden NaN NA, de nem minden NA NaN
x <- c(1, 3, 4, NaN, 5, NA)
x
Az is.X()
(itt X helyére a konkrét tipust kell írni) kifejezéssel ellenőrizhető, egy változó az adott tipusú-e:
x <- c(1, 3, 4, NaN, 5, NA)
is.numeric(x)
is.na(x)
arr <- array(1:12, c(3, 2, 2))
is.array(arr)
is.numeric(arr)
is.factor(arr)
Legegyszerűbben a c()
szintaxissal lehet összekombinálni két változót:
cbind, c, rbind, abind,
a<- 1:10
b<- 11:20
lista<-c(a,b)
lista
Ha van két vektorunk/mátrix/array akkor ezek kombinálása történhet oszlop szereint (cbind()
) vagy sorok mentén (rbind()
):
cbind(x = 1:3, y = 4:6) # ket vektor osszeillesztese egy-egy oszlopba
mat2 <- matrix(1:4, 2, 2)
mat3 <- matrix(5:8, 2, 2)
cbind(mat2, mat3) # Figyelem mátrixoknál a sorok a sorok számának egyezni kell!
rbind(x = 1:3, y = 4:6) #kombinálás sorok mentén
(Kivéve listák és data.frame-k esetében!)
vec <- c(1:2, 4)
vec[2:3]
mat <- matrix((1:8)^2, 2, 4)
mat[1, ]
mat[, 2]
mat[1:5]
Ez eltér a pythontól, mivel itt lehetőség van attribútomok kezelésével (nevet adni mondjuk az adattábla oszlopainak). Ez a szintaxis a python pandas csomaghoz hasonló
Ha névvel akarunk hivatkozni az elemekre, a "$ jelet kell használni:
x<-c('A','B')
y<-6:9
z<-1:8
d<-data.frame(x,y,z)
d
str(d)
attributes(d)
d$x
d$y[2:5]
c(2:20:2)
d$z[2:5]
A függvényeket a "function
" paranccsal hozhatjuk létre:
simpleAdd <- function(x, y) x + y
# ha megadjuk az argumentum nevét, a sorrend lényegtelen
simpleAdd(y = 4, x = 2)
fv_ertek <- simpleAdd(y = 4, x = 2)
str(fv_ertek)
Bonyolúltabb dolgokat "{}"-k közé kell rendezni. Ez eltér a Python-tól!
func2<-function(x,y){
z=x+y
return(z)
}
func2(1,2)
Alap szintaxis:
if (test_expression) {
statement
}
Vagy else
ággal:
if (test_expression) {
statement1
} else {
statement2
}
x <- -5
if(x > 0){
print("Non-negative number")
} else {
print("Negative number")
}
while
ciklus az R-ben¶Alap szintaxis:
while (test_expression)
{
statement
}
i <- 1
while (i < 6) {
print(i)
i = i+1
}
# ha az 'y' argumentum hiányzik, adja össze az 'x' vektor elemeit
advAdd <- function(x, y) {
if (missing(y)) {
out <- sum(x)
} else {
out <- x + y
}
return(out)
}
# ha nem adunk meg argumentumnevet, akkor a függvény
# argumentumainak eredeti sorrendje számít
simpleAdd(2, 4)
Az R-ben számos módszer létezik fájlok kezelésére. Most a leggakrabban használt módot mutatjuk meg szöveges adatfájlok beolvasására.
Első lépésben megadható a munkakönvtár a setwd("..")
, amit most ne változtassunk meg. A getwd()
paranccsal lekérdezhető az aktuális munkakönyvtár:
getwd()
dir() # megjeleníti a könyvtár tartalmát
Adatfájlokat többek között a read.csv
paranccsal tudunk megtenni. Ez a parancs alapértelmezésben vesszővel elválaszott fájlokat olvas be, illetve alapértelmezett úgy veszi, hogy a fájlnak van fejléce.
Nézzük meg a működését az ismert "h_vs_t.txt" fájlon (Baumgartner-es példafeledat volt).
dat_txt <- read.csv(file = "data/h_vs_t.txt")
str(dat_txt)
Ez így nem lesz jó, hiszen az első sor nem a fejléc volt. Használjuk a "hearder=False" kapcsolót:
dat_txt <- read.csv(file = "data/h_vs_t.txt", header=F) # False rövidíthető egy "F" billentyűvel (True pedig "T"-vel)
str(dat_txt)
Még mindig nem jó, hiszen számokról van szó, és a faktor tipus nem erre utal. Ahhoz hogy a szóközzel elválasztott oszlopkat kezelni tdjuk, használjuk a sep=" "
parancsot:
dat_txt <- read.csv(file = "data/h_vs_t.txt", header=F, sep = " ")
str(dat_txt)
head(dat_txt$V1) # a head() parancsat hasznolóan működik, mint a Pythonban
Az adatok egyszerű ábrázolása a plot()
paranccsal történik:
plot(dat_txt)
Számos lehetőség van a plot parancsal módosítására, ám a Pythonnal ellentétben, itt a plot parancson belül kell többségüket kiadni.
help(plot)
plot(dat_txt, xlab="Idő [s]", ylab="Magasság [m]", main="Ugrás",
log="xy", xlim=c(0.1,1000), col="blue3", pch=2, type="b")
Ábramagyarázatot a legend()
paranccsal tudunk elhelyezni.
Szintakxisa:
legend(Pozició,Nevek, ...)
Több adatsort úgy lehet 1 ábrán megmutatni, hogy külön plot parancsokat használunk, és a plot parancsok közé kitesszük:
par(new=True)
parancsot! Itt figyelni kell a tengelyfeliratok beállítására. A második ábáránál célszerű a semmit ("") megadni.
plot(dat_txt$V1, xlab="Idő [s]", ylab="Magasság [m]", main="Ugrás",
xlim=c(0,400),ylim=c(0,40000), col="green", pch=16, type="b")
par(new=T)
plot(dat_txt$V2, xlab="", ylab="",
xlim=c(0,400),ylim=c(0,40000), col="orange", pch=16, type="b")
legend(300, 40000, c("Magasság", "Eltelt idő"), col=c("orange", "green"), pch = 16)
Most csak a lineáris illesztést mutatjuk be, de lehetőség van egyéb görbék illesztésére is.
A lineáris illesztést az lm()
paranccsal lehet elvégezni:
x<-dat_txt[dat_txt>=210 & dat_txt<=240,1]
y<-dat_txt[dat_txt>=210 & dat_txt<=240,2]
lm(y ~ x)
Figyeljünk oda, hogy a kimenet egy komplex objektum:
fit<-lm(y~x)
str(fit)
Próbáljuk meg használni a korábban már bemutatott summary()
parancsot. Itt már kihasználhatjuk az R statisztikai képességeit, hiszen az illesztésről megtudjuk mennyire szignifikáns a fit. Látható, hogy ebben az esetben az illesztés hibája kicsi, és annak az esélye, hogy véletlenül lehet egyenest illeszteni $<2\cdot10^{-16}$, azaz nulla.
summary(fit)
FIGYELEM: Az illesztett egyenes ábrázolása kicsit körülményes:
Az illesztett adatok a változó "coefficients" nevő listájában vannak. Az első elem az y tengelymetszet, míg a második elem a meredeksés, azaz:
fit$coefficients[2]
fit$coefficients[1]
plot(x,x*fit$coefficients[2]+fit$coefficients[1], type="l", col="red"
, xlab="", ylab="",xlim=c(210,240),ylim=c(3500,6000))
par(new=T)
plot(x,y, pch=3, col="green", xlab="Idő [s]", ylab="Magasság [m]",xlim=c(210,240),
ylim=c(3500,6000), main="Illesztés")
Alternatív módszer a predict()
parancs használatával:
plot(x,predict(fit), type="l", col="red"
, xlab="", ylab="",xlim=c(210,240),ylim=c(3500,6000))
par(new=T)
plot(x,y, pch=3, col="green", xlab="Idő [s]", ylab="Magasság [m]",xlim=c(210,240),
ylim=c(3500,6000), main="Illesztés")
cor(x,y)
cor.test(x,y)
cor(x,y, method = "spearman")
Egyszerű leíró statisztika a summary
paranccsal lekérdezhető:
random<-runif(n = 20, min = 10, max = 30) # runif normál eloszlású véletlen számokat gerenál
summary(random)
A medián, az átlag, a szórás (sztenerd hiba) illetve a variancia (szórásnégyzet) számítására vannak külön parancsok is:
median(x) # Medián
mean(x) # Számtani átlag
sd(x) # Normál hiba (szórás)
var(x) # Variancia, ennek a gyöke a szórás
Véletelen egész számok generálására használjuk a sample
függvényt. Ez a függvény használatos, ha egy listából véletlenszerűen szeretnénk kiválasztani elemeket. A replace = True
opcióval pedig visszatevéses kiválasztást/generálást is végre lehet hasjtani.
sample(x=10)
sample(y, size = 5, replace = T)
Listák sorbarendezésére használatos a sort()
függvény.
random<-runif(20)
sort(random)
sort(random,decreasing = T) #ez csökkenő sorrendeben rendez
Itt lehetőség van a sorbarendezési indexeket is megnézni az index.return=True
beálítással:
sort(random,index.return=T)
Az R ismeri a legfontosabb eloszlástipusokat, mint a normál, binominális, $\chi^2$, cauchy, exponenciális és még sok mást.
x<-seq(-3,3,0.1)
plot(x,dnorm(x),type="l",main="dnorm()")
Az R számos statisztikai tesztet ismer az R:
Példa T-próbára:
Egy gyárban egy gépnek 500 g töltőanyagot kell a konzervekbe juttatnia minden töltéskor. A töltőanyag egyenetlenségéből adódóan a gép néha kicsit többet, néha kicsit kevesebbet tölt, mint 500 g. Arra vagyunk kíváncsiak, hogy a gép átlagos "teljesítménye" 500 g-nak mondható-e. Kiveszünk 10 konzervet a futószalagról és megmérjük mindben a töltőanyag súlyát. Az eredmények rendre 483, 502, 498, 496, 502, 483, 494, 491, 505, 486.
Vizsgáljuk meg, hogy szignifikánsan eltér-e az átlagtól a termelés?
x<- c(483, 502, 498, 496, 502, 483, 494, 491, 505, 486)
t.test(x, mu=500, conf.level = 0.05) # A táblázatbeli határérték 95%-os szignifikancia szinten: 1.833
A nullhipotézist elvetjük, az egymintás t-próba szerint az átlagos töltőtömeg szignifikánsan eltér (p = 0,05-ös szignifikancia szint mellett) az 500 g-tól.
A Kolmogorov–Szmirnov próba egy olyan statisztikai teszt, ami két minta eloszlásának összehasonlítására alkalmas. Alkalmas arra, hogy két valószínűségi változó eloszlását összehasonlítsuk, vagy ellenőrizzük, hogy egy valószínűségi változónak csakugyan az az eloszlása, amit feltételeztünk.
x <- c(1,2,2,3,3,3,3,4,5,6)
y <- c(2,3,4,5,5,6,6,6,6,7)
z <- c(12,13,14,15,15,16,16,16,16,17)
ks.test(x,y)
ks.test(x,z)
A Shapiro-Wilk teszt azt vizsgálja, hogy a minták normál eloszlásból származik-e?
shapiro.test(x)
shapiro.test(y)
shapiro.test(z)
shapiro.test(dnorm(x)) # Ez így egy nomrális eloszlásű adatsort vizsgál
Két változó korrelációjnak tesztelésére a cor.test
használandó. A korreláció kiszámolásának mintájára, itt is többféle korrelációt vizsgálhatunk.
x<-dat_txt[dat_txt>=210 & dat_txt<=240,1]
y<-dat_txt[dat_txt>=210 & dat_txt<=240,2]
cor.test(x,y)
cor.test(x,y, method = "spearman")