2 . Kapitulua Oinarrizko datu-egiturak

R lengoaian oinarrizkoak diren zenbait datu-egitura mota daude. Liburu honen helburua sarrera labur bat eskaintzea denez, bakarrik lau datu-egitura mota ohikoenak aztertuko ditugu, bektoreak, matrizeak, zerrendak eta data-frameak.

2.1 Bektoreak

R lengoaiaren oinarrizko datu egitura bektorea da. Adibidez elementu bakarreko aldagai bat 1 tamainako bektore bezala ulertzen du Rk:

x <- 2.45
x
## [1] 2.45

Orainarte ulertzen ez genuen [1] sinboloak, horixe adierazten du hain zuzen, x bektorearen 1. elementua erakusten ari zatzaigula.

Elementu bat baino gehiagoko bektore bat sortzeko c funtzioa erabiliko dugu era honetan:

x <- c(2, 6, 1, 5)
x
## [1] 2 6 1 5
y <- c(1, 4)
y
## [1] 1 4

Bestalde, c funtzioa erabil dezakegu ere bi bektore bata bestearen atzean lotzeko:

z <- c(x, y)
z
## [1] 2 6 1 5 1 4

Gainera, hurrenez hurreneko zenbakiez osatutako bektore bat sortzeko : eragilea erabili dezakegu, bai goruntz eta bai beherunzko bektoreak lortuz:

x <- c(2:7)
x
## [1] 2 3 4 5 6 7
y <- c(7:2)
y
## [1] 7 6 5 4 3 2

Ohartu, bektore bateko elementu guztiak mota berdinekoak izan behar dutela. Mota ezberdineko elementuak konbinatuz gero, Rk denak mota batekoak bihurtuko ditu, normalean guk nahi ez ditugun aldaketak eginez.

x <- c("kaixo", 3, 4, 5)
x
## [1] "kaixo" "3"     "4"     "5"

Aurreko adibidean, adibidez, zenbakiak ere karaktere bilakatu ditu.

Bestalde, bektore baten elementuak atzitzeko [] sintaxia erabiltzen da:

x <- c(1, 4, 7, 2, 5)
x[3]
## [1] 7

Adibidean ikus daitekeen bezala, edozein bektoreko lehenengo balioaren indizea 1 da. Gainera, Rk 0 luzerako bektoreak definitzeko aukera ere eskeintzen du:

bektore.hutsa <- vector()
bektore.hutsa
## logical(0)

Azkenik, bektoreen gaineko zenbait oinarrizko eragiketa egin ditzakegu Rn. Hasteko bi bektoreen arteko batuketa, kenketa eta eskalar batekin biderkaketa egin ditzakegu, hauek ohiko moduan egiten direlarik:

x <- c(1, 1, 1, 1, 1)
y <- c(1, 2, 3, 4, 5)
x+y
## [1] 2 3 4 5 6
x*7
## [1] 7 7 7 7 7

Bektoreen arteko batuketa edo kenketa egitean, zer gertatzen da bektoreak tamaina ezberdinekoak direnean?. Pentsa genezake aginduak errore bat jaurtiko lukeela, baina hori ez da gertatzen dena, jarraian dagoen adibidean ikus daitekeen bezala.

x <- rep(5, 10)
y <- 1:5
x - y
##  [1] 4 3 2 1 0 4 3 2 1 0
z <- 1:3
x * z
## Warning in x * z: longer object length is not a multiple of shorter object
## length
##  [1]  5 10 15  5 10 15  5 10 15  5

Lehenengo adibidean x bektoreak 10 elementu ditu4, baina y bektoreak bakarrik 5. Kenketa egiten dugunean lortzen dugun bektoreak 10 elementu ditu, x bektorearen lehenengo 5 elementuei y kenduta eta, jarraian, x bektorearen azken 5 elementuei y berriz ere kenduta. Emaitza hori R lengoaian bektoreak birziklatu egiten direlako lortzen da. Hau da, 10 tamainako bektore bat behar bada eta daukagun bektorearen tamaina soilik 5 bada, 10 tamainako bektore bat sortzen da 5 tamainakoa errepikatuz. Beste era batera esanda, lehenengo adibidean x bektoreari 1:5 kendu beharrean c(1:5, 1:5) kendu diogu.

Bigarren adibidean gauza bera gertatzen da, baina abisu bat jasotzen dugu, zrekin xren tamainako bektorerik ezin delako sortu–izan ere, 10 ez da 3ren multiploa–. Birziklapena zenbait egoeratan oso praktikoa egingo zaigu –adibidez, x bektorearen elementu guztiei 1 gehitzeko x + 1 besterik ez dugu egin behar–. Programazio estilo honek ordea, programatzailearen aldetik lengoaiaren ezagutza handia eskatzen du.

Bestalde, matematika arloan ondo definituta ez dauden beste zenbait eragiketa ere egin ditzakegu bektoreekin Rn. Adibidez, bi bektore biderkatu edo zatitu ditzakegu. Eragiketa hauek elementuz elementu aplikatuko dira:

x*y
##  [1]  5 10 15 20 25  5 10 15 20 25
x/y
##  [1] 5.000000 2.500000 1.666667 1.250000 1.000000 5.000000 2.500000
##  [8] 1.666667 1.250000 1.000000

Gainera, aurreko atalean ikusi ditugun eragiketa logikoak bektoreekin ere erabil ditzakegu, hauek bektoreko elementu bakoitzari banan banan aplikatzen zaizkiolarik:

x <- c(1, 3, 4, 5, 6, 7)
x > 5
## [1] FALSE FALSE FALSE FALSE  TRUE  TRUE

Azkenik, Rko bektoreak algebrako multzoak bezala ulertzen baditugu, multzo teoriako operazioak ere burutu ditzakegu hauen gainean. Adibidez:

  • Bildura: Bi bektoreetan dauden elementu guztiak hartuko ditu, errepikapenik gabe.
  • Ebakidura: Bi bektoreetan aldi berean dauden elementuak hartuko ditu.
  • Barne: Balio bat bektore baten barruan dagoen konprobatuko du, TRUE ala FALSE itzuliz.

Eragiketa hauen adibide batzuk honakoak dira:

x <- c(1, 2, 3, 6, 7, 8)
y <- c(1, 2, 5, 9, 10)
union(x, y) #Bildura
## [1]  1  2  3  6  7  8  5  9 10
intersect(x, y) #Ebakidura
## [1] 1 2
6 %in% x #Barne
## [1] TRUE

2.2 Matrizeak eta arrayak

Matrizeak 2 dimentsiotako egiturak dira eta matrix funtzioaren bitartez sortu ditzakegu:

m <- matrix(1:12, nrow=3, byrow=FALSE)
m
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    2    5    8   11
## [3,]    3    6    9   12

Ikusten dugunez, lehenengo parametro gisa, matrizean sartu nahi ditugun balioak jarriko ditugu bektore batean. Ondoren, errenkada kopurua zehaztuko dugu nrow parametroan (edo zutabe kopurua ncol parametroan). Azken parametroak matrizea zein ordenetan beteko den adierazten du, zutabeka (byrow=FALSE) edo errenkadaka (byrow=TRUE).

Gainera, errenkadei eta zutabeei izenak eman diezazkiekegu, colnames eta rownames funtzioak erabiliz:

colnames(m) <- c("W", "X", "Y", "Z")
rownames(m) <- c("A", "B", "C")
m
##   W X Y  Z
## A 1 4 7 10
## B 2 5 8 11
## C 3 6 9 12

Matrizeak 2 dimentsiotako egiturak dira, Rk ordea, hainbat dimentsiotako egiturak sortzeko aukera ematen digu. Horrelako objektuak sortzeko array funtzioa erabil daiteke, dim parametroan egituraren dimentsioak zehaztuz:

a <- array(1:12, dim = c(1, 2, 3))
a
## , , 1
## 
##      [,1] [,2]
## [1,]    1    2
## 
## , , 2
## 
##      [,1] [,2]
## [1,]    3    4
## 
## , , 3
## 
##      [,1] [,2]
## [1,]    5    6

Ikusten dugunez, kasu honetan, array-ak 3 dimentsio dauzka. 1. dimentsioaren tamaina 1 da (matrizeen errenkada kopurua), bigarrenarena (matrizeen zutabeen kopurua) 2, eta hirugarrenarena 3 (matrize kopurua).

Matrizeen zein array -en elementuak atzitzeko kortxete sinpleak erabiltzen dira, dimentsio guztien indizeak –edo izenak– erabiliz. Hona hemen adibide batzuk:

m[1, 1]
## [1] 1
m["A", "Y"]
## [1] 7
a[1, 1, 2]
## [1] 3

Indizeak zenbaki bakar bat ez ezik, bektoreak ere izan daitezke:

m[c(1, 3), 2:3]
##   X Y
## A 4 7
## C 6 9

Gainera, elementuak atzitzeko beste bi sintaxi berezi ere existitzen dira. Indize jakin bat zehaztu ordez, dimentsio bat hutsik utziz gero, dimentsio horren elementu guztiak atzituko dira. Bestalde, aukeratutako indizeen aurretik - zeinua jarriz gero, indize horiei dagozkien elementuak ezik, beste guztiak atzituko dira:

m[,-1]
##   X Y  Z
## A 4 7 10
## B 5 8 11
## C 6 9 12
m[-(1:2) , ]
##  W  X  Y  Z 
##  3  6  9 12

Gainera, Rn hainbat eragiketa matrizial ere egin ditzakegu:

  • A + B: Matrizeen batuketa.
  • A - B: Matrizeen kenketa.
  • A * B: Elementuz elementu egindako matrize biderkaketa.
  • A / B: Elementuz elementu egindako matrize zatiketa.
  • **A %*% B**: Matrize biderkaketa algebraikoa.

Ohartu, lehen lau eragiketa hauetan matrizeen dimentsioak berdinak izatea komeni dela, nahi dugun emaitza lortu nahi badugu. Bestalde, azken eragiketan, matrizeen biderkaketa ohikoan, matrizeen dimentsioak (nxm) eta (mxp) modukoak izan behar dute, hau da, lehenengoaren zutabe kopurua, bigarrenaren errenkada kopuruaren berdina izan behar du.

Azkenik, bektoreei bezala, matrizeei ere operadore aritmetiko eta logikoak aplika dakizkiegu, operadoreak elementuz elementu aplikatzen direlarik:

m>4
##       W     X    Y    Z
## A FALSE FALSE TRUE TRUE
## B FALSE  TRUE TRUE TRUE
## C FALSE  TRUE TRUE TRUE

Ohartu, operadore konplexuak edo haien konbinazioak ere aplika ditzakegula:

((m>4) & (m%%2==0))
##       W     X     Y     Z
## A FALSE FALSE FALSE  TRUE
## B FALSE FALSE  TRUE FALSE
## C FALSE  TRUE FALSE  TRUE

Adibidez, kasu honetan, m-ko elementuak 4 baino handiagoak eta bikoitiak diren ala ez aztertzen dugu.

2.3 Zerrendak

Bektoreetan elementu guztiak mota berdinekoak izan behar dira. Alabaina, kasu askotan bektore heterogeneoak ere beharko ditugu; hauek list edo zerrenda motako objektuen bidez adierazten dira. Adibide gisa, zerrenda batean izena, e-posta eta telefono zenbakia gorde dezakegu:

contact <- list("Izena", "izena@server.com", 555652332)
contact
## [[1]]
## [1] "Izena"
## 
## [[2]]
## [1] "izena@server.com"
## 
## [[3]]
## [1] 555652332

Zerrenda bateko elementuak edozein objektu mota izan daitezke, baita bektoreak edo matrizeak ere:

zerrenda <- list(x, y, m)
zerrenda[[1]]
## [1] 1 2 3 6 7 8
zerrenda[[3]]
##   W X Y  Z
## A 1 4 7 10
## B 2 5 8 11
## C 3 6 9 12

Adibidean ikusten den moduan, zerrenda bateko elementuak atzitzeko kortxete bikoitza –[[]]– erabiltzen da5.

Ondoren, zerrenda bateko objektu zehatz bat atzitu ondoren, bere gaineko atzipenak ere burutu ditzakegu. Adibidez honako aginduek, zerrendako 3. elementuko (1,2) posizioan dagoen balioa itzuliko digu, hau da, m matrizearen (1,2) posizioko balioa:

zerrenda[[3]][1,2]
## [1] 4

2.4 data-frameak

Bektoreen gisa, matrizeak datu egitura oso erabilgarriak dira, baina eragozpen bat dute: bertan gordetako elementu guztiak mota berekoak izan behar dute. Hau da, matrize batean ezin dugu zutabe numeriko bat eta, aldi berean, character motako zutabe bat izan. Baina ohiko datu baseak mota ezberdinetako aldagaiak (zutabeak) izaten dituzte orohar.

Hau hala, R lengoaian, mota ezberdinetako zutabeak dituzten taulak data.frame objektu motaren bidez adierazi daitezke. Izatez, data.frameak posizio bakoitzean tamaina berdineko bektore bat gordetzen duten zerrendak dira eta zerrenda bezala ere tratatu daitezke, baina haien erabilgarritasuna dela eta, izaera propioa eman zaie. Objektu mota hauek eraikitzeko data.frame funtzioa erabiltzen da:

df <- data.frame("String" =c("A", "B", "C"), 
                 "Number" =10:12, 
                 "Logical"=c(TRUE, TRUE, FALSE))
df
##   String Number Logical
## 1      A     10    TRUE
## 2      B     11    TRUE
## 3      C     12   FALSE

data.frame baten zutabeen edo aldagaien izenak ezagutzeko names atributua erabil dezakegu:

names(df)
## [1] "String"  "Number"  "Logical"

Gainera, data frame baten lehen lerroak edo azken lerroak ikusteko, head eta tail funtzioak erabil ditzakegu, ikusi nahi ditugun lerro kopurua zehaztuz:

head(df, n=2)
##   String Number Logical
## 1      A     10    TRUE
## 2      B     11    TRUE
tail(df, n=3)
##   String Number Logical
## 1      A     10    TRUE
## 2      B     11    TRUE
## 3      C     12   FALSE

Gainera, data.frame-etan atzipenak, matrizeetan edo zerrendetan bezala egin daitezke:

df[1, 2] # 1. errenkadako 2. elementua atzitzen du.
## [1] 10
df[1, ]  # 1.errenkada atzitzen du
##   String Number Logical
## 1      A     10    TRUE
df[, 2] # 2. zutabea atzitzen du
## [1] 10 11 12
df[[2]] # 2. zutabea atzitzen du
## [1] 10 11 12

Baina, gainera, zutabeak izena badute, $ eragilea ere erabil dezakegu aldagai oso bat atzitzeko:

df$Logical
## [1]  TRUE  TRUE FALSE

Era berean, aldagai berriak ere sor ditzakegu, $ eragilea eta eragiketa bektorialak erabiliz:

df$Number2 <- df$Number*2
df$Number3 <- df$Number > 11
df
##   String Number Logical Number2 Number3
## 1      A     10    TRUE      20   FALSE
## 2      B     11    TRUE      22   FALSE
## 3      C     12   FALSE      24    TRUE

Azkenik, ohartu, atzipen konplexuagoak egiteko, operadore logikoak ere erabil ditzakegula. Adibidez, df datu basetik soilik Logical aldagaia TRUE duten eta Number aldagaia gutxienez 11 duten errenkadak aukeratu nahi baditugu:

df[df$Logical==TRUE & df$Number>=11, ]
##   String Number Logical Number2 Number3
## 2      B     11    TRUE      22   FALSE

2.5 Ariketak

1. Ariketa Sortu honako bektoreak Rn:

  • \(x=(1, 3, 5, 7)\)
  • \(y=(2, 4, 6, 8)\)
  • \(z=(7, 5, 3, 1)\)
  • \(t=(8, 6, 4, 2)\)

2. Ariketa Egin \(x\) eta \(z\) bektoreen arteko kenketa (orden honetan). Bektore berriaren zein posizio dira -3 baino txikiagoak? -5 balioa lortutako kenduren artean agertzen al da?

3. Ariketa Sortu matrize bat, \(m\) izenekoa, \(x, y, z\) eta \(t\) bektoreak zutabetzat dituenak. Horretarako, berrerabili iada definituta dituzun aldagaiak. Ondoren, ordezkatu matrize honen 3. zutabea bere 2. eta 3. zutabeen baturagatik.

4. Ariketa Sortu zerrenda bat \(x\), \(y\), \(m\) eta zure izena gordetzen dituenak (orden horretan). Ondoren, atzitu zerrenda honetatik \(x\) bektorearen 2. elementua eta \(m\) matrizearen (2,3) posizioan dagoen elementua.

5. Ariketa iris datu basea Rn berez dagoen data frame bat da. Berau erabiliz egin honako ariketak:

  • Zeintzuk dira datu base honen aldagaiak?
  • Bistaratu datu basearen lehen 5 lerroak.
  • Aukeratu, Species aldagaian setosa balioa duten indibiduoak.
  • Aukeratu Sepal.Length 4.5 baino handiagoa eta Petal.Width 0.3 baino txikiagoa edo berdina duten indibiduoak.
  • Petal.Width aldagaia cm-tan dago neurtuta. Sortu aldagai berri bat, Petal.Width2 izenekoa aldagai bera m-tan ematen duena eta gehitu aldagai berri hau iris datu baseari.

  1. Ohartu, rep funtzioak bektore bat sortzen duela, elementu bat, 5 kasu honetan, errepikatuz hainbat aldiz, 10 kasu honetan.

  2. Kortxete bakarra erabiltzen badugu, hasiera batean, emaitza berdina dela pentsa genezake, baina ezberdintasu handi bat dago: zerrendan dagoen elementu soila lortu beharrean 1 tamainako zerrenda bat lortuko dugu, atzitu nahi dugun elementua gordeko duena.