Liste

Lista je generički vektor koji sadrži druge objekte.

n <- c(2, 3, 5)
s <- c("aa", "bb", "cc", "dd", "ee")
b <- c(TRUE, FALSE, TRUE, FALSE, FALSE)
lst <- list(n, s, b)   # lst sadrzi  kopije od n, s, b

lst[1] #niz n
## [[1]]
## [1] 2 3 5
lst[2] #niz s
## [[1]]
## [1] "aa" "bb" "cc" "dd" "ee"

Na ovaj način dobijamo kopije prvog, odnosno drugog člana liste
Međutim ako hoćemo da direktno pristupimo članu liste koristimo [[ ]]

lst[[1]]   
## [1] 2 3 5

Tada možemo da mijenjamo sadržaj liste

lst[[2]]<-c("a","b")
lst[[2]][1]<-"c"

Data frame

brojevi<-1:12
slova<-letters[1:12]
df<-data.frame(brojevi,slova)
df
##    brojevi slova
## 1        1     a
## 2        2     b
## 3        3     c
## 4        4     d
## 5        5     e
## 6        6     f
## 7        7     g
## 8        8     h
## 9        9     i
## 10      10     j
## 11      11     k
## 12      12     l
df$brojevi
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12
df$slova
##  [1] a b c d e f g h i j k l
## Levels: a b c d e f g h i j k l
names(df)<-c("kolona1", "kolona2")
attach(df)
kolona1 # inace bismo pristupali sa df$kolona1
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12
df[,2]
##  [1] a b c d e f g h i j k l
## Levels: a b c d e f g h i j k l
df[1]
##    kolona1
## 1        1
## 2        2
## 3        3
## 4        4
## 5        5
## 6        6
## 7        7
## 8        8
## 9        9
## 10      10
## 11      11
## 12      12

Neki primjeri baza podataka.

data("AirPassengers")
AirPassengers
##      Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
## 1949 112 118 132 129 121 135 148 148 136 119 104 118
## 1950 115 126 141 135 125 149 170 170 158 133 114 140
## 1951 145 150 178 163 172 178 199 199 184 162 146 166
## 1952 171 180 193 181 183 218 230 242 209 191 172 194
## 1953 196 196 236 235 229 243 264 272 237 211 180 201
## 1954 204 188 235 227 234 264 302 293 259 229 203 229
## 1955 242 233 267 269 270 315 364 347 312 274 237 278
## 1956 284 277 317 313 318 374 413 405 355 306 271 306
## 1957 315 301 356 348 355 422 465 467 404 347 305 336
## 1958 340 318 362 348 363 435 491 505 404 359 310 337
## 1959 360 342 406 396 420 472 548 559 463 407 362 405
## 1960 417 391 419 461 472 535 622 606 508 461 390 432
summary(AirPassengers)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   104.0   180.0   265.5   280.3   360.5   622.0

Važni funkcionali u R-u

Funkcionalima ćemo ovdje zvati funkcije koje primaju funkciju kao argument i vraćaja vektor kao izlaz. Jednostavan primjer funkcionala: funkcija koju kreiramo treba da vrati vrijednosti funkcije koja je proslijedjena kao argument u datim tačkama iz uniformne raspodjele.

funkcional <- function(f) {
  f(runif(1000))
}
funkcional(mean)
## [1] 0.4916365
funkcional(sum)
## [1] 472.7689
funkcional(var)
## [1] 0.08020371

Tri funkcionala koja se najčešće koriste su: lapply(), apply() i tapply().
Česta upotreba funkcionala je zamjena za for petlje, za koje važi da rade sporo u R-u. Nije uvijek slučaj da će upotreba funkcionala proizvesti najbrži kod, ali se preporučuje zbog jednostavnijeg zapisa koda, lakšeg uočavanja problema i razvijanja alata koji se koriste da riješe široku klasu problema.

lapply

  • uzima funkciju, primjenjuje je na svaki element u listi i vraća rezultat u formi liste.
  • napisan je u C-u, ali možemo napisati jednostavnu R implementaciju koji radi istu stvar:
lapply2 <- function(x, f) {
  out <- vector("list", length(x))
  for (i in seq_along(x)) {
  out[[i]] <- f(x[[i]])
  }
  out
}

Primjer

# Pravimo neke podatke pomocu slucajnih brojeva

l <- replicate(20, runif(sample(1:10,1)),simplify = F) # simplify=F ce nam dati podatke u obliku liste

# Hocemo da dobijemo vektor duzina svakog od 20 elemenata ove liste


# Resenje sa for petljom


out<- vector("list", length(l))
for( i in seq_along(l)){
  out[[i]] <- length(l[[i]])
}
unlist(out)  # unlist nam daje jednostavniju verziju liste u vidu vektora koji sadrzi njene podatke
##  [1]  9  9  7  1  6 10  8  2  3  9  7  9  9  6  2  9  4  5  2 10
# mogli smo da pozovemo i samo `out` 

# Resenje sa lapply


unlist(lapply(l,length))
##  [1]  9  9  7  1  6 10  8  2  3  9  7  9  9  6  2  9  4  5  2 10

Kako je “data frame” takodje lista, lapply() je korisna kada hoćemo nešto da radimo sa svakom kolonom.

# Baza `mtcars`

mtcars
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
# Primjer1: zanima nas koje klasi su podaci u svakoj koloni

unlist(lapply(mtcars,class))
##       mpg       cyl      disp        hp      drat        wt      qsec 
## "numeric" "numeric" "numeric" "numeric" "numeric" "numeric" "numeric" 
##        vs        am      gear      carb 
## "numeric" "numeric" "numeric" "numeric"
# Primjer2: želimo da podijelimo svaku kolonu sa srednjom vr.

mtcars[]<-lapply(mtcars, function(x) x/mean(x))
# mtcars

Funkcije srodne lapply koje na izlazu daju vektore: sapply i vapply

df <- data.frame(x=1:10, y=letters[1:10])
sapply(df,class) # "pogadja tip podataka na izlazu"
##         x         y 
## "integer"  "factor"
vapply(df, class, character(1)) # "tip izlaza se zadaje kao argument"
##         x         y 
## "integer"  "factor"

apply i tapply za data frame i matrice

apply(X, MARGIN, FUN, ...)

Argumenti:

  • X- matrica

  • MARGIN- odredjuje indeks za dio matrice na koji treba da bude primijenjena funkcija, npr. 1-za vrste, 2-za kolone

  • FUN-sumarna funkcija

  • … ostali opcioni argumenti koji se odnose na funkciju FUN

Jednostavan primjer:

a <- matrix(runif(20), ncol = 4, nrow = 5)
a
##            [,1]      [,2]      [,3]       [,4]
## [1,] 0.01152352 0.2374907 0.7183384 0.89700779
## [2,] 0.03050023 0.6147648 0.5692699 0.97480502
## [3,] 0.47331415 0.5809281 0.2923093 0.47602682
## [4,] 0.99749332 0.1770159 0.1526841 0.55353065
## [5,] 0.19500236 0.5529109 0.6784285 0.05839393
apply(a,1,mean) # racunamo srednju vrijednost po vrstama
## [1] 0.4660901 0.5473350 0.4556446 0.4701810 0.3711839
apply(a,2,mean) # racunamo srednju vrijednost po kolonama
## [1] 0.3415667 0.4326221 0.4822060 0.5919528
apply(a, c(1,2), function(x) x^2) # kvadriramo sve elemente matrice
##              [,1]       [,2]       [,3]        [,4]
## [1,] 0.0001327914 0.05640182 0.51601004 0.804622984
## [2,] 0.0009302639 0.37793580 0.32406827 0.950244828
## [3,] 0.2240262844 0.33747746 0.08544471 0.226601535
## [4,] 0.9949929237 0.03133462 0.02331244 0.306396175
## [5,] 0.0380259221 0.30571048 0.46026526 0.003409851

Funkcija apply nema argument simplify pa ne možemo da zadamo koji tip izlaza želimo. To znači da ako je koristimo unutar neke druge funkcije treba biti oprezan kojeg tipa su ulazni podaci.

sweep

x<-matrix(rnorm(20,0,10), nrow = 4)
x
##            [,1]        [,2]       [,3]        [,4]      [,5]
## [1,]   4.662218 -7.73986414   6.606557 -14.6390696 33.549287
## [2,]   7.337004 -5.43866058   5.239908   3.3166891 -7.932929
## [3,]  -6.924635 -0.09918982  12.609025  -0.9345136  2.746065
## [4,] -22.594851 12.09370682 -14.541598  -7.7727668 11.940250
x1<-sweep(x,1,apply(x,1,min),'-')
x1
##          [,1]      [,2]      [,3]      [,4]     [,5]
## [1,] 19.30129  6.899205 21.245626  0.000000 48.18836
## [2,] 15.26993  2.494269 13.172838 11.249619  0.00000
## [3,]  0.00000  6.825445 19.533660  5.990121  9.67070
## [4,]  0.00000 34.688558  8.053253 14.822084 34.53510
x2<-sweep(x,1,apply(x,1,max),'/')
x2
##            [,1]         [,2]       [,3]        [,4]       [,5]
## [1,]  0.1389662 -0.230701301  0.1969209 -0.43634518  1.0000000
## [2,]  1.0000000 -0.741264491  0.7141755  0.45204951 -1.0812219
## [3,] -0.5491808 -0.007866573  1.0000000 -0.07411466  0.2177857
## [4,] -1.8683148  1.000000000 -1.2024104 -0.64271169  0.9873111

outer
* pravi matricu tako što primjenjuje zadatu funkciju na više različitih vektora koji su joj proslijeđeni kao argumenti

outer(1:3, 1:10,"*")
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,]    1    2    3    4    5    6    7    8    9    10
## [2,]    2    4    6    8   10   12   14   16   18    20
## [3,]    3    6    9   12   15   18   21   24   27    30
outer(rep(1,3),rep(1,4),"-")
##      [,1] [,2] [,3] [,4]
## [1,]    0    0    0    0
## [2,]    0    0    0    0
## [3,]    0    0    0    0

tapply

  • koristi se kada dopuštamo da niz ima redove različitih dužina, odnosno različiti broj kolona po redovima
    Primjer: Vrši se neko medicinsko ispitivanje i imamo podatke za vrijednost pulsa od dvije grupe pacijenata, A i B. Želimo da uporedimo te grupe.
# Pravimo vektor tako da prvih 10 pacijenata (grupa A) ima puls u skladu sa normalnom (70,10/3) raspodjelom a za drugih 12 (grupa B) ima srednju vrijednost vecu za 5
pulse <- round(rnorm(22,70,10/3))+rep(c(0,5),c(10,12))
pulse
##  [1] 69 69 70 73 73 74 66 71 76 72 78 70 74 76 77 73 76 74 73 73 75 73
group <- rep(c("A","B"),c(10,12))

tapply(pulse, group, length)
##  A  B 
## 10 12
tapply(pulse, group, mean)
##        A        B 
## 71.30000 74.33333
# ako zadamo simplify=F vraca listu


t<-tapply(pulse, group, sd)
t
##        A        B 
## 2.907844 2.188122
t[[1]]
## [1] 2.907844
t[[2]]
## [1] 2.188122