Tommaso C. & Marco G.
16 - 18 Novembre 2016
In R
esistono strutture di controllo specifiche per regolare il flusso di esecuzione di un programma:
Le istruzioni possono essere raggruppate insieme utilizzando le parentesi graffe. Una sequenza di istruzioni fra parentesi graffe costituisce un blocco
Un blocco non viene quasi mai usato da solo, ma in combinazione con un’altra istruzione
{
x <- 4+2
z <- 4
x+z
x-3
}
## [1] 3
{
x <- 4+2
z <- 4
x+z
x-3
}
## [1] 3
Differenze ?
x <- 4+2
z <- 4
x+z
## [1] 10
x-3
## [1] 3
Si, la valutazione delle singole istruzioni nel caso dei blocchi è di tipo lazy (rimandata al termine del blocco), questo comporta, per esempio, che l’output dell’operazione x+z
non sia visibile.
x <- 6
if ( x %% 3 == 0 ){
x <- x + 6
x - 3
} else {
x + 3
}
## [1] 9
Sintassi:
{
x <- 120
if (x >= 100)
x <- x + 4
else
x <- x - 200
if(x<0)
x <- x + 2000
x
}
## [1] 124
N.B. Questo tipo di sintassi però è valida solo all’interno di un blocco (potete provare ad incollare il codice senza le parentesi graffe)
Esistono diverse forme di istruzioni di loop:
Tutte permettono di ripetere un blocco di istruzioni
Sintassi:
v = c(2,5,7,8)
for (i in v){
print(i)
}
## [1] 2
## [1] 5
## [1] 7
## [1] 8
N.B. La semantica di questo comando è pari al foreach di java, quindi di fatto non avete una variabile i
come contatore che si incrementa ad ogni ripetizione
Su cosa posso iterare?
R
, quello che ottengo è la valutazione di tutte le funzionivalore = 24
funzioni = list(sqrt, sum1, log, exp)
for (f in funzioni){
print(f(valore))
}
## [1] 4.898979
## [1] 25
## [1] 3.178054
## [1] 26489122130
Sintassi:
i <- 0
while (i < 2){
print (i)
i<-i+1
}
## [1] 0
## [1] 1
Sintassi:
i <- 0
repeat{
print (i)
i <- i + 1
if (i >= 2) break;
}
## [1] 0
## [1] 1
N.B. La differenza principale con while
è che posso eseguire del codice prima di valutare la condizione (do while
)
R
su vettori operareno elemento per elementofor
Esempio calcolare il vettore sommma tra due vettori v
e w
. Useremo system.time()
per calcolare il tempo di esecuzione
v <- sample (1:400, 100000, replace = TRUE)
w <- sample (400:800, 10000, replace = TRUE )
system.time(for(e in 1:length(w)) v[e] <- v[e] + w[e] )
## user system elapsed
## 0.020 0.003 0.023
system.time(v <- v + w)
## user system elapsed
## 0.001 0.000 0.000
Ovviamente in R
è possibile creare delle funzioni personalizzate usando la parola chiave function
return
# Definizione della funzione successore
succ <- function(x=0){
return(x+1)
}
expY <- function(x=0,y){
return(y^x)
}
expY(,3)
## [1] 1
expY(3,2)
## [1] 8
expY(y = 2, x = 3)
## [1] 8
N.B. La seconda e la terza chiamata sono assolutamente identiche, in expY(3,2)
la posizione del valore indica a quale parametro della funzione associarlo, in expY(y = 2, x = 3)
il valore del parametro viene definito per nome
.R
la vostra funzione e usare il comando source("nomeFile.R")
per importare il file# esempioScript.R
expY <- function(x=0,y){
return(y^x)
}
.R
la vostra funzione e usare il comando source("nomeFile.R")
per importare il filerm(list = ls())
source("esempioScript.R")
expY(3,2)
## [1] 8
In una delle slide precendenti abbiamo visto che è possibile ciclare su una lista di funzioni, ovvero applicare una dopo l’altra una serie di funzioni ad un singolo valore. Qualora invece sia necessario applicare una singola funzione a tutti i valori di un vettore/matrice/lista/datframe è possibile usare le funzioni lapply
e sapply
; mentre lapply
restituisce una sempre una lista, sapply
restituisce una matrice se applicato ad un dataframe e un vettore altrimenti
y <- sample(1:10, 2, replace=TRUE)
f <- function(el){
if(el%%2==0)
return(TRUE)
else
return(FALSE)
}
lapply(y, f)
## [[1]]
## [1] TRUE
##
## [[2]]
## [1] TRUE
sapply(y, f)
## [1] TRUE TRUE
Perché non applichiamo direttamente la funzione f sul vettore?
f(y)
## Warning in if (el%%2 == 0) return(TRUE) else return(FALSE): the condition
## has length > 1 and only the first element will be used
## [1] TRUE
Usando le istruzioni viste oggi, scrivere le seguenti funzioni R
e salvarle nel file mia_libreria.R
table
)table
)table
)N.B. Come ottenere una copia di un vettore senza duplicati
vector = c ("pippo", "pluto", "pluto", "paperino", "paperino", "pluto", "paperino", "paperino")
unique (vector)
## [1] "pippo" "pluto" "paperino"
quantile()
) il percentile \(k\)-esimo dei dati un vettore (\(k\) deve essere un parametro della funzione)foo <- function(x,y){
x <- x + y
print(paste("x dentro la funzione foo", x, sep = " "))
}
x <- 3
y <- 3
foo(x, y)
## [1] "x dentro la funzione foo 6"
x
## [1] 3
In R è possibile bypassare il passaggio per valore utilizzando il doppio simbolo di minore: la variabile x viene modificata solo nell’ambiente da cui è stata effettuata la chiamata, non dentro la funzione; se non viene trovata, viene creata e inizializzata
foo <- function(x,y){
x <<- x + y
print(paste("x dentro la funzione foo", x, sep = " "))
}
x <- 3
y <- 3
foo(x, y)
## [1] "x dentro la funzione foo 3"
x
## [1] 6