Részletesebb leírást a Hands-On Programming with R könyv The Very Basics fejezetében találtok.
Az RStudio kezdőfelülete így néz ki:
Alapértelmezetten a konzol/parancssor ablak van megnyitva, ahol a >
sornál az R várja a parancsokat, amiket Enter leütése után azonnal futtat, pl.:
> 10 + 20
[1] 30
Megjegyzés Az eredménynél a [1]
azt jelenti, hogy ez a sor az eredmény első tagjával kezdődik. Vannak olyan parancsok, amik több mint egy értéket adnak vissza, ezért meglehet hogy több sort töltenek meg. Például a 100:130
parancs 31 értéket ad vissza: egy egész számokból álló sorozatot 100-tól 130-ig.
> 100:130
[1] 100 101 102 103 104 105 106 107 108 109 110 111 112
[14] 113 114 115 116 117 118 119 120 121 122 123 124 125
[25] 126 127 128 129 130
Például itt a második sor a 14. értékkel, az utolsó sor pedig a 25. értékkel kezdődik.
Environment és files
Jobb oldalon felül az Environment ablakban látjuk majd a létrehozott változókat, vagy itt gyorsan be lehet tölteni adatokat is, illetve a jobb alsó ablakban látjuk a fájlokat. Ha át szeretnénk állítani a mappát, ahová jelenleg az R mentené a dokumentumokat (working directory), akkor azt például megtehetjük úgy, hogy a File ablakban a \(\dots\) gombra kattintva kiválasztjuk a mappát, ezután a More opciónál rákattintunk a “Set as Working Directory”-ra. Másik opció ha beírjuk a Console-ba hogy
setwd("mappa eleresi utvonala")
Az új fájl készítése gombnál (vagy Ctrl+Shift+N
) létrehozhatunk többek között egy R script fájlt is:
Ahelyett hogy egyesével írnánk a parancsokat az R konzolba, kényelmesebb ha azokat egymás után írjuk egy R script file-ba, amit aztán akár egyszerre, akár kijelölt részenként tudunk futtatni:
Az R-ben nyilakkal lehet értékeket adni a változóknak. Például egy új script file-ban a következő sorokban az x
és y
értékét 1
-re állítom:
x <- 1
1 -> y
Ha ezt lefuttatom (Ctrl+Shift+Enter), akkor az Environment ablakban megjelenik ez a két változó az értékeikkel együtt:
Ha olyan parancsot írunk a script-be aminek van visszatérési értéke, akkor az a Console-ban fog megjelenni. Például ha ki szeretnénk írni hogy mi az x
értéke akkor egészítsük ki a scriptet egy új sorral:
x <- 1
1 -> y
print(x) # Ha print(x) helyett csak x-et írok, akkor is kiírja az értékét.
## [1] 1
(Kommentet írni a #
karakterrel tudtok.)
Megjegyzés
A változókat bárminek nevezheted, de van néhány szabály: nem kezdődhet számmal, illetve nem tartalmazhat speciális karaktereket, például:^
, !
, $
, @
, +
, -
, /
, vagy *
. Valamint az R case-sensitive azaz name
és Name
lehet két különböző változó.
Ha azt szeretnénk hogy x = 2
és y = 2
akkor például ezt egyszerre is megtehetjük:
x <- 2 -> y
print(x)
## [1] 2
print(y)
## [1] 2
Megjegyzés
Általában működik az =
operátor is értékadásnál, de van (lehet) néhány különbség főleg régebbi verzióknál, úgyhogy inkább használjuk a nyilakat, ahogy az R közösség is szokta
x = 3
print(x)
## [1] 3
:
függvényKorábbi példában már láttátok hogy a :
függvény úgy működik mint a Pythonban a range()
függvény azzal a kivétellel, hogy az R teljesen inklúzív, azaz amíg a Python esetében a range(2, 4)
csak a 2-t és a 3-t tartalmazza, addig az R 2:4
a 2 3 4
számokat tartalmazó vektort adja vissza.
dobokocka <- 1:6
dobokocka
## [1] 1 2 3 4 5 6
c
függvényR-ben a c
függvénnyel lehet létrehozni egy listát, de ha vegyes típusú értékeket adunk meg neki, akkor azok át lesznek konvertálva egy típusúra:
x <- c(1, 2, 3)
print(x)
## [1] 1 2 3
x <- c(1, 2, TRUE, FALSE)
print(x)
## [1] 1 2 1 0
x <- c(1, 2, "A", "B", TRUE, FALSE)
print(x)
## [1] "1" "2" "A" "B" "TRUE" "FALSE"
list
függvényA list
függvény már tud kezelni vegyes típusú adatokat:
numerical_data <- c(1, 2, 10, 3.5)
class(numerical_data) # A class függvénnyel lehet lekérni az objektumok típusát.
## [1] "numeric"
string_data <- c("alma", "körte", "eper", "szilva")
class(string_data)
## [1] "character"
binary_data <- c(TRUE, FALSE, TRUE, FALSE)
class(binary_data)
## [1] "logical"
x <- list(numerical_data, string_data, binary_data)
print(x)
## [[1]]
## [1] 1.0 2.0 10.0 3.5
##
## [[2]]
## [1] "alma" "körte" "eper" "szilva"
##
## [[3]]
## [1] TRUE FALSE TRUE FALSE
Mátrixokat a matrix
függvénnyel tudunk létrehozni, aminek 3 fontos paramétere van: data
(amivel fel akarjuk tölteni), nrow
(sorok száma, opcionális) ncol
(oszlopok száma, opcionális)
matrix(dobokocka, nrow = 2)
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
Megjegyzés Alapértelmezetten oszloponként tölti fel a mátrixot, de ha azt szeretnénk hogy soronként töltse fel, akkor állítsuk a byrow
paramétert TRUE
-ra:
matrix(dobokocka, nrow = 2, byrow = TRUE)
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
Az array
függvénnyel \(n\)-dimenziós array-eket készíthetünk. Készítsünk egy 3-dimenziós tömböt: \(3\) db \(2\times2\)-es mátrixot:
ar <- array(c(11:14, 21:24, 31:34), dim = c(2, 2, 3))
ar
## , , 1
##
## [,1] [,2]
## [1,] 11 13
## [2,] 12 14
##
## , , 2
##
## [,1] [,2]
## [1,] 21 23
## [2,] 22 24
##
## , , 3
##
## [,1] [,2]
## [1,] 31 33
## [2,] 32 34
A numerikus vektorok/listák úgy működnek mint a Python numpy array-ek, azaz a műveleteket elemenként végzi el (element-wise execution).
Példák:
numerikus_lista <- c(1,5,10)
numerikus_lista + 1
## [1] 2 6 11
numerikus_lista /2
## [1] 0.5 2.5 5.0
numerikus_lista * 10
## [1] 10 50 100
numerikus_lista * numerikus_lista
## [1] 1 25 100
numerikus_lista * c(2, 0.4, 0.2)
## [1] 2 2 2
Természetesen lehet mátrix szorzást is végezni: skaláris/belső (inner) szorzathoz a %*%
operátort, külső (outer) szorzáshoz a %o%
operátort kell használni:
numerikus_lista %*% numerikus_lista
## [,1]
## [1,] 126
1:6 %o% 1:6
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 2 3 4 5 6
## [2,] 2 4 6 8 10 12
## [3,] 3 6 9 12 15 18
## [4,] 4 8 12 16 20 24
## [5,] 5 10 15 20 25 30
## [6,] 6 12 18 24 30 36
Ugyanúgy működik mint minden más programozási nyelven, de fontos hogy a lista első elemének az indexe 1 nem pedig 0 (hasonlóan a MATLAB-hoz vagy Wolfram Language-hez).
Lista első eleme:
numerikus_lista[1]
## [1] 1
Lista első három eleme
numerikus_lista[1:3]
## [1] 1 5 10
Lista első és harmadik eleme:
numerikus_lista[c(1, 3)]
## [1] 1 10
Fontos hogy a lista[1]
és a lista[[1]]
sokszor ugyanannak tűnik, de valójában a lista[1]
a lista első elemét tartalmazó 1-hosszú listát ad vissza, míg a lista[[1]]
a lista első elemét adja vissza. Például:
lista = list(1, "hello", TRUE)
class(lista[3])
## [1] "list"
class(lista[[3]])
## [1] "logical"
Fontos hogy itt a -i
-edik elem nem azt csinálja amit várnánk. Legyen a listánk lista <- c("a", "b", "c")
, ekkor lista[-1]
visszaadja az összes elemet, kivéve az elsőt:
lista <- c("a", "b", "c")
lista[-1]
## [1] "b" "c"
lista[-2]
## [1] "a" "c"
A szűrés hasonló a numpy array-ek szűréséhez. Például ha a listának csak azokra az elemeire vagyunk kíváncsiak, amikre teljesül egy logikai kifejezés, akkor azt a következőképpen tehetjük meg:
numerikus_lista <- c(1, 5, 10, 3, 4.5, 6.7, 23)
numerikus_lista[numerikus_lista > 4]
## [1] 5.0 10.0 4.5 6.7 23.0
A mátrixok indexelése nagyon hasonló a vektorokhoz:
mtx <- matrix(1:36, ncol = 6)
mtx
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 1 7 13 19 25 31
## [2,] 2 8 14 20 26 32
## [3,] 3 9 15 21 27 33
## [4,] 4 10 16 22 28 34
## [5,] 5 11 17 23 29 35
## [6,] 6 12 18 24 30 36
Az mtx
mátrix \(i\)-edik sorának \(j\)-edik elemét az mtx[i, j]
kifejezéssel kérhetjük le:
mtx[1,3]
## [1] 13
Ha több sort/oszlopot akarunk lekérni akkor itt is a :
operátor vagy c
lista megadásával tudjuk:
mtx[1:3, 1:3]
## [,1] [,2] [,3]
## [1,] 1 7 13
## [2,] 2 8 14
## [3,] 3 9 15
mtx[c(2,4,6), c(1,3,5)]
## [,1] [,2] [,3]
## [1,] 2 14 26
## [2,] 4 16 28
## [3,] 6 18 30
Ha az összes sort/oszlopot le szeretnénk kérni, de nem feltétlenül az összes oszlopban/sorban akkor azt így tehetjük meg:
mtx[, 3] # harmadik oszlop
## [1] 13 14 15 16 17 18
mtx[1, ] # első sor
## [1] 1 7 13 19 25 31
mtx[1, 6:1] # első sor visszafelé
## [1] 31 25 19 13 7 1
Az R data frame objektumai olyanok mint a Python pandas DataFrame objektumai, azaz a data frame egy táblázat, lényegében olyan mint egy Excel sheet. Adatelemzéshez ezek az objektumok a leghatékonyabbak.
A data frame-ek összecsoportosítják a vektorokat egy 2-dimenziós táblázatba. A data frame-et elképzelhetjük úgy is, mint egy listát, ami egyforma hosszú vektorokból áll. Minden vektor egy oszlopa lesz a táblázatnak, ennek következtében az oszlopok lehetnek különböző adattípusúak, de egy oszlopon belül minden cellának ugyanolyan típusúnak kell lennie, ahogy az alábbi ábra is mutatja:
Példa: Data frame-et általában sosem szoktunk kézzel begépelni, de most a példa kedvéért megmutatom hogyan lehet a data.frame
függvény segítségével kézzel létrehozni egy data frame-t.
df <- data.frame(nev = c("Baranyi Máté", "Bolla Marianna", "Kói Tamás", "Mala József", "Nagy Marcell"),
kurzus = c("T1", "T0", "EN1", "EN0", "T2"),
hallgatok_szama = c(18, 38, 13, 13, 20))
df
## nev kurzus hallgatok_szama
## 1 Baranyi Máté T1 18
## 2 Bolla Marianna T0 38
## 3 Kói Tamás EN1 13
## 4 Mala József EN0 13
## 5 Nagy Marcell T2 20
Töltsük be az órán használt koleszterines adathalmazt (jobb gomb, mentés másként). Olyan helyre mentsük, ahol az elérési útvonalban nincsen ékezetes betű, mert akkor karakterkódolásból fakadó hibából nem biztos hogy megtalálja az R 😒.
A leggyorsabban az Environment ablak “Import Dataset” gombjával tudunk betölteni adatot. Itt kattintsunk rá a “From Text (base)…”:
Ezután válasszuk ki a letöltött cholestr.txt
fájlt, majd a következő ablak jön be:
Itt többek között be tudjuk állítani hogy mi legyen a betöltött data.frame
neve, milyen karakterrel vannak elválasztva egymástól az értékek, vagy hogy az adatokban milyen karakter választja el a tizedesjegyeket. Mivel az adatoknak van fejléce (Day2, Day4, Day14), ezért állítsuk a Heading-et Yes-re:
Ha ez után gy tűnik, hogy minden minden rendben van, akkor menjünk az Import gombra. Ekkor egy új lapon kapunk egy képet a data frame-ről:
Látjuk a Consoleban, hogy a következő parancs futott le mikor betöltöttük az adatokat:
> cholestr <- read.delim("./cholestr.txt")
> View(cholestr)
Itt az elsősorban a read.delim
paranccsal olvasta be az adatot, majd mentette el a cholestr
változóba. A második sorban szereplő View
függvénnyel lehet megnézni, hogy hogyan néz ki a data frame-ünk.
Illetve az Environment ablakban megjelent a cholestr
, és látjuk hogy 28 sora és 3 oszlopa van. (Megjegyzés: itt rákattintva a cholestr sorára szintén meg tudjuk nézni a táblázatot)
Az oszlop neveket lekérhetjük a colnames
függvénnyel:
colnames(cholestr)
## [1] "Day2" "Day4" "Day14"
A data frame-ek elemeit ugyanúgy lehet lekérni mint a mátrixokét, viszont ha fejléccel el van látva a data frame, akkor az oszlopait a $
jellel is lehet lekérni:
cholestr$Day2
## [1] 270 236 210 142 280 272 160 220 226 242 186 266 206 318 294 282 234 224 276 282 360 310 280 278 288 288 244 236
cholestr[, 1]
## [1] 270 236 210 142 280 272 160 220 226 242 186 266 206 318 294 282 234 224 276 282 360 310 280 278 288 288 244 236
mean(cholestr$Day2)
## [1] 253.9286
A write.csv
, vagy write.xlsx
függvényekkel gyorsan kiírhatjuk a data frame-eket CSV vagy Excel file-ba.
Megjegyzés A write.csv
függvényhez nem szükséges külön csomag, viszont a write.xlsx
függvényhez telepítenünk kell az openxlsx
vagy xlsx
csomagot.
write.csv(cholestr, file='cholestr.csv', row.names=FALSE)
library(openxlsx)
write.xlsx(cholestr, file='cholestr.xlsx', row.names=FALSE)
Az R-ben 5 féle objektumban tudunk adatokat tárolni (lásd alábbi ábra). Ezek közül a data frame-ek a leghasznosabbak és a legjobbak statisztikai/adattudományi elemzésekhez.
Hasonlóan a Python-hoz, rengeteg beépített függvény van az R-ben, illetve szintén hasonlóan végtelen sok csomagot (később) lehet telepíteni és betölteni, amivel még további hasznos függvényekhez juthatunk hozzá.
Példák:
dobokocka <- 1:6
mean(dobokocka) # Átlag
## [1] 3.5
round(mean(dobokocka)) # Kerekített átlag
## [1] 4
lista <- c(1, 2, 2, 4, 5, 1)
length(lista) # Lista hossza
## [1] 6
median(lista) # Medián
## [1] 2
Mintavételezni a sample
függvénnyel lehet, aminek 4 paramétere van, amiből kettő opcionális:
x
(amiből vesszük a mintát),size
(hány darabot vegyünk),replace
(visszatevéses/visszatevés nélküli mintavételezés, alapértelmezetten FALSE),prob
(az egyes elemeket mekkora valószínűséggel húzzuk).Például ezzel a függvénnyel tudunk dobókocka dobálásokat szimulálni:
sample(x = 1:6, size=10, replace = TRUE)
## [1] 2 3 4 5 2 5 4 3 2 5
A saját függvényeknek a szintaxisa így néz ki:
fuggveny_nev <- function() {}
Ahol a fuggveny_nev
a függvényünknek a neve, a function()
függvény ()
zárójelében adhatunk meg paramétereket és esetleg ezek default értékét. A {}
kapcsos zárójelbe írjuk a függvén törzsét, azaz, hogy mit végezzen el a függvény.
Példák: Írjunk egy függvényt, ami szimulál két dobókocka dobást és eredményül visszaadja a két számnak az összegét.
roll <- function() {
die <- 1:6
dice <- sample(die, size = 2, replace = TRUE)
sum(dice)
}
roll()
## [1] 9
roll()
## [1] 4
Változtassuk meg ezt a függvény úgy, hogy legyen egy dobókocka paramétere die
, és ne a függvényen belül definiáljuk:
roll1 <- function(die) {
dice <- sample(die, size = 2, replace = TRUE)
sum(dice)
}
roll1(die = 1:6)
## [1] 7
roll1(1:32)
## [1] 34
Legyen a die
paraméter alapértelmezett (default) értéke a számok 1-től 6-ig:
roll2 <- function(die = 1:6) {
dice <- sample(die, size = 2, replace = TRUE)
sum(dice)
}
roll2()
## [1] 4
roll2(die = c(10))
## [1] 6
if
, for
és while
függvényekEzeknek a függvényeknek is hasonló a szintaxisa:
if
statementAz if
szintaxisa a következő:
if (test_expression) {
statement
}
Ha a test_expression
igaz (TRUE
), akkor a statement
rész lefut, de ha FALSE
, akkor semmi nem történik. Mint minden másik programozási nyelvben, a test_expression
lehet logikai változó vagy numerikus, utóbbi esetben a 0 jelenti a FASLE
-t, minden más szám pedig TRUE
.
x <- 5
if(x > 0){
print("Positive number")
}
## [1] "Positive number"
for
loopA for
szintaxisa a következő:
for (value in sequence) {
statement
}
Itt a sequence
egy vektor/lista, és a value
változó végigmegy a sequence
elemein. Minden egyes iterációban a statement
végrehajtódik.
A következő példában megszámoljuk a páros számokat egy listában:
x <- c(2,5,3,9,8,11,6)
count <- 0
for (val in x) {
if(val %% 2 == 0) {
count = count+1
}
}
print(count)
## [1] 3
while
loopA wile
szintaxisa a következő:
while (test_expression) {
statement
}
A test_expression
kiértékelődik és ha e TRUE
, akkor belép a ciklus törzsébe, és lefut a statement
. Ezután újra kiértékelődik a test_expression
, és ez a folyamat ismétlődik amíg a test_expression
FALSE
nem lesz.
i <- 1
while (i < 6) {
print(i)
i = i+1
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
Szerencsére nem kell minden függvényt nekünk megírni, hiszen rengeteg R csomag (package) létezik.
Minden csomag a http://cran.r-project.org weboldalon van hosztolva, de nem kell felmenni az oldalra, ahhoz hogy letölts és telepíts egy R csomagot.
Kétféleképpen megmutatom hogyan lehet a ggplot2
ábra készítő csomagot telepíteni: parancssorból és felhasználói felületről:
install.packages
install.packages("ggplot2")
library
Ahhoz, hogy használni tudjuk a csomagok függvényeit, be is kell töltenünk őket, ezt a library
függvénnyel lehet megtenni. Például a ggplot2 csomagot így kell betölteni:
library(ggplot2) #library("ggplot2") is működik
A Hands-On Programming with R könyv Packages fejezetében illetve a Appendix 2: R packages fejezetében találtok egy részletes leírást.
x <- seq(-1, 1, 0.1) # -1-től 1-ig a számok 0.1-esével
y <- x^3
qplot(x, y)
Többféleképpen lehet segítséget kérni az R-től a függvényekkel kapcsolatban:
F1
gombot, akkor a Help ablakban megkapjuk a leírást.?
és ??
operátorok használata: hasonlóan ha beírjuk a Consoleba vagy a scriptbe egy függvény nevét, és eléírunk egy ?
karaktert ??
karaktereket, akkor megkapjuk a függvény leírását.Töltsük be a stats
, graphics
és utils
csomagokat.
library(stats)
library(graphics)
library(utils)
A következő nevezetes eloszlásokat használjuk:
Generáljunk 100-100 standard normális, 1 rátájú (\(\lambda=1\)) exponenciális, és \([0,1]\)-en egyenletes eloszlású valváltozókat, és ezeket tegyük bele egy data frame oszlopaiba:
normalis <- rnorm(n=100, mean=0, sd=1)
exp <- rexp(n=100, rate=1)
uniform <- runif(n=100, min=0, max=1)
df <- data.frame(norm=normalis, exp=exp, unif=uniform)
Egy data frame-nek a leíró statisztikáit könnyen lekérhetjük a summary
függvénnyel:
summary(df)
## norm exp unif
## Min. :-2.581391 Min. :0.01555 Min. :0.0004173
## 1st Qu.:-0.693979 1st Qu.:0.40278 1st Qu.:0.2772574
## Median :-0.009266 Median :0.72066 Median :0.5326263
## Mean : 0.037925 Mean :1.10339 Mean :0.5272164
## 3rd Qu.: 0.904524 3rd Qu.:1.53743 3rd Qu.:0.7819619
## Max. : 3.289232 Max. :5.06474 Max. :0.9967928
Általában nem túl átláthatóak a 3D plotok, de most ábrázoljuk ennek a data frame-nek a három oszlopát egy 3-dimenziós felhő diagramon (scatter plot-on)
Ehhez telepíteni kell az rgl
csomagot.
library(rgl)
plot3d(df$norm, df$exp, df$unif, col="blue", size=3)
A 3D ábrát egy új ablakban kapjuk meg, ami valahogy így néz ki:
Rákattintva és a gombot lenyomva tartva el tudjuk forgatni az ábrát, úgy ahogy szeretnénk:
Végezzük el a második napi koleszterines adatokon a t-próbát. Ehhez először töltsük be az adatokat:
cholestr <- read.delim("./cholestr.txt") # be lehet tölteni a read.table függvénnyel is, de ott alapértelmezetten a header paraméter FALSE.
A t-próba elvégzése R-ben nagyon egyszerű: a t.test
függvényt kell hozzá meghívni. Tegyük fel hogy az elméleti várhatóértéke a második napi koleszterin szintnek 260.
t.test(cholestr$Day2, mu=260)
##
## One Sample t-test
##
## data: cholestr$Day2
## t = -0.67337, df = 27, p-value = 0.5064
## alternative hypothesis: true mean is not equal to 260
## 95 percent confidence interval:
## 235.4284 272.4288
## sample estimates:
## mean of x
## 253.9286
Ennek az eredményében több mindent is látunk, például a konfidencia intervallumot is, ami [235.4284, 272.4288], tehát nyugodtan elfogadhatjuk a nullhipotézist, azaz hogy habár a mintaátlag 253.9286, ez lehet a véletlen következménye is és igaz lehet hogy valójában 260 az átlagos második napi koleszterinszint (a t.test
függvény alapértelmezett konfidencia szintje 0.95).
A hipotézis vizsgálatok esetén a nullhipotézis elfogadásának/elutasítása a p-értéken és a konfidencia szinten múlik, de erről majd a következő anyagrészben lesz részletesen szó.
Megjegyzés
Sok parancsnak a kimenete névvel ellátott lista. Például az előző parancs a következő változókat adja vissza:
cholestr_ttest = t.test(cholestr$Day2, mu=260)
names(cholestr_ttest)
## [1] "statistic" "parameter" "p.value" "conf.int" "estimate" "null.value" "stderr" "alternative" "method" "data.name"
Például ha csak a konfeidencia intervallumra vagyunk kiváncsiak, azt így kérhetjük le (hasonlóan, mint a data frame-ek oszlopait):
cholestr_ttest$conf.int
## [1] 235.4284 272.4288
## attr(,"conf.level")
## [1] 0.95