Sesija 03: Kontrola toka u R + uvod u {dplyr} i {tidyverse}

Fidbek se upućuje na goran.milovanovic@datakolektiv.com. Ova sveščica prati kurs Uvod u R programiranje za analizu podataka 2020/21.


U Sesiji 03 bavimo se osnovama kontrole toka u R. To podrazumeva upoznavanje načina na koji se u ovom programskom jeziku donose odluke i kako se iteracijama (“petljama”) automatizuju repetitivni zadaci. Pokazaćemo osnove if... else... konstrukcije u R, i upoznati for, while, i repeat petlje. Ne zaboravite: u funkcionalnom programskom jeziku kao što je R imamo na raspolaganju druga sredstva osim petlji i u suštini petlje želimo da koristimo što manje!

0. Kontrola toka u programskom jeziku R

Jednostavno donošenje odluke: ako je ispunjen određeni uslov uradi jedno, ako nije - uradi nešto drugo:

a <- 2

if (a >= 5) {
  print("a is larger or equal to 5.")
} else {
  print("a is lesser than 5.")
}
## [1] "a is lesser than 5."

Podsetnik: - u programskom jeziku R, uslov iza if mora da ide u zagrade, kao u kodu iznad; - { i } se koriste da označe početak i kraj bloka koda - skup instrukcija koje će biti izvršene u zavisnosti od toga kakva je odluka doneta u odnosu na uslov u if konstrukciji.

A sad, nešto divno: vektorizovano odlučivanje u R pomoću ifelse() funkcije!

data(iris)
iris$LongSepalLength <- 
  ifelse(iris$Sepal.Length >= 4.8, "long", "short")
head(iris)

Zadatak: hoćemo da isprintamo kvadarate svih parnih brojeva do 100. Prvo rešenje, pomoću for petlje:

my_vec <- seq(2, 100, by = 2)
my_vec_sq <- numeric(length = length(my_vec))

for (i in 1:length(my_vec)) {
  
  my_vec_sq[i] <- my_vec[i]^2
  
}
my_vec_sq
##  [1]     4    16    36    64   100   144   196   256   324   400   484   576   676   784   900  1024  1156  1296  1444  1600  1764  1936  2116
## [24]  2304  2500  2704  2916  3136  3364  3600  3844  4096  4356  4624  4900  5184  5476  5776  6084  6400  6724  7056  7396  7744  8100  8464
## [47]  8836  9216  9604 10000

Vektorizovana forma: kao i sve ostalo, operacija (preciznije, u R je to funkcija) stepenovanja…

my_vec_sq <- my_vec ^ 2
my_vec_sq
##  [1]     4    16    36    64   100   144   196   256   324   400   484   576   676   784   900  1024  1156  1296  1444  1600  1764  1936  2116
## [24]  2304  2500  2704  2916  3136  3364  3600  3844  4096  4356  4624  4900  5184  5476  5776  6084  6400  6724  7056  7396  7744  8100  8464
## [47]  8836  9216  9604 10000

Konačno, forma sa upotrebom lapply() funkcije:

my_vec_sq <- lapply(my_vec, function(x) {
  x ^ 2
})
my_vec_sq <- unlist(my_vec_sq)
my_vec_sq
##  [1]     4    16    36    64   100   144   196   256   324   400   484   576   676   784   900  1024  1156  1296  1444  1600  1764  1936  2116
## [24]  2304  2500  2704  2916  3136  3364  3600  3844  4096  4356  4624  4900  5184  5476  5776  6084  6400  6724  7056  7396  7744  8100  8464
## [47]  8836  9216  9604 10000

Pošto lapply() uvek vraća listu, morali smo da iskoristimo u gornjem kodu unlist() kako bismo dobili vektor kao rezultat. Funkcija sapply(), bliska rođaka lapply(), pojednostavljuje rezultat te funkcije u vektor automatski:

my_vec_sq <- sapply(my_vec, function(x) {
  x ^ 2
})
my_vec_sq
##  [1]     4    16    36    64   100   144   196   256   324   400   484   576   676   784   900  1024  1156  1296  1444  1600  1764  1936  2116
## [24]  2304  2500  2704  2916  3136  3364  3600  3844  4096  4356  4624  4900  5184  5476  5776  6084  6400  6724  7056  7396  7744  8100  8464
## [47]  8836  9216  9604 10000

Evo i repeat petlje:

# - repeat petlja
a <- 0
repeat {
  
  a <- a + 1
  print(a)
  
  # - condition
  if (a >= 10) {
    break
  }

}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10

Ne zaboravite: u programskom jeziku R morate eksplicitno sami da uvedete uslov za izlazak iz repeat petlje; ako ga nema - dobija se beskonačna petlja!

Sintaksička konstrukcija while petlje u R izgleda ovako:

a <- 10

while (a > 1) {
  print(a)
  a <- a - 1
}
## [1] 10
## [1] 9
## [1] 8
## [1] 7
## [1] 6
## [1] 5
## [1] 4
## [1] 3
## [1] 2

Upotreba break kako bi se izašlo iz petlje:

a <- seq(1, 100, by = 1)
for (i in 1:length(a)) {
  
  if (a[i] %% 2 == 0) {
    
    print(paste0("Square is: ", a[i]^2))
    
  }
  
  if (a[i] == 50) {
      
    break
  
  }
  
}
## [1] "Square is: 4"
## [1] "Square is: 16"
## [1] "Square is: 36"
## [1] "Square is: 64"
## [1] "Square is: 100"
## [1] "Square is: 144"
## [1] "Square is: 196"
## [1] "Square is: 256"
## [1] "Square is: 324"
## [1] "Square is: 400"
## [1] "Square is: 484"
## [1] "Square is: 576"
## [1] "Square is: 676"
## [1] "Square is: 784"
## [1] "Square is: 900"
## [1] "Square is: 1024"
## [1] "Square is: 1156"
## [1] "Square is: 1296"
## [1] "Square is: 1444"
## [1] "Square is: 1600"
## [1] "Square is: 1764"
## [1] "Square is: 1936"
## [1] "Square is: 2116"
## [1] "Square is: 2304"
## [1] "Square is: 2500"

Instrukcije break i next, za izlazak iz petlje i za prelazak u narednu iteraciju, mogu da se koriste i u repeat i while petljama.

Čitanje za narednu sesiju

R Markdown

R Markdown je ono što koristimo da bismo razvili ove sveščice. Evo knjige iz koje se može naučiti rad u toj jednostavnoj ekstenziji R: R Markdown: The Definitive Guide, Yihui Xie, J. J. Allaire, Garrett Grolemunds..


Goran S. Milovanović, Data Scientist & Vlasnik, DataKolektiv.
Kontakt: goran.milovanovic@datakolektiv.com. Ovo je besplatan i slobodan softver: GPL v2.0.