Programmazione
Nelle lezioni precedenti abbiamo utilizzato R come un ambiente statistico a linea di comando, dove far girare degli script, invocando delle funzioni.
In questa lezione ci focalizzeremo sulla creazione di funzioni.
Ciao
Iniziamo con un esempio molto semplice: la creazione della funzione ciao()
, il cui scopo è quello di salutare.
ciao <- function() {
messaggio <- "ciao a tutti"
return (messaggio)
}
Invochiamo la funzione
ciao()
[1] "ciao a tutti"
Passaggio di un argomento
La versione seguente richiede un parametro (un nome) che verrà usato per personalizzare il saluto
ciaoNome <- function (nome) {
messaggio <- paste("ciao ", nome, ", come stai?", sep="" )
return (messaggio)
}
Se invochiamo la funzione senza il parametro, R segnalerà un errore.
ciaoNome("Francesco")
[1] "ciao Francesco, come stai?"
# ciaoNome() # il parametro è obbligatorio
Valore di default
In questa iterazione, assegnamo al parametro nome
un valore di default, che verrà usato se, nell'invocazione, non verrà specificato alcun valore.
ciaoNomeAmico <- function (nome="amico") {
messaggio <- paste("ciao ", nome, ", come stai?", sep="" )
return (messaggio)
}
ciaoNomeAmico("Marika")
[1] "ciao Marika, come stai?"
ciaoNomeAmico()
[1] "ciao amico, come stai?"
If
In questa iterazione gestiamo la presenza o meno del parametro nell'invocazione.
Se il parametro non c'è, salutiamo l'anonimo.
ciaoNomeForse <- function (nome=NULL) {
messaggio <- ""
if(!is.null(nome)) {
messaggio <- paste("ciao ", nome, ", come stai?", sep="" )
} else {
messaggio <- "Ciao anonimo ;)"
}
return (messaggio)
}
ciaoNomeForse("Matteo")
[1] "ciao Matteo, come stai?"
ciaoNomeForse()
[1] "Ciao anonimo ;)"
For
In questa iterazione, gestiamo un vettore di più nomi, introducendo il ciclo for
.
ciaoNomi <- function (nomi=c()) { # c() vettore vuoto
messaggio <- "ciao "
for (nome in nomi) {
messaggio <- paste(messaggio, nome, ", ", sep="")
}
messaggio <- paste(messaggio, "come state?", sep="")
return (messaggio)
}
nomi <- c("Mario", "Antonella", "Lucia")
ciaoNomi(nomi)
[1] "ciao Mario, Antonella, Lucia, come state?"
ciaoNomi()
[1] "ciao come state?"
If, else, for
Una versione più complessa, che gestisce un parametro (con valore di default, ovvero il vettore vuoto), e 4 diversi scenari: vettore vuoto, vettore con un solo valore, vettore con meno di 4 valori (di fatto 2 o 3 nomi), vettore con almeno 4 valori.
ciaoDipende <- function (nomi=c()) { # c() vettore vuoto
if (length(nomi)==0) {
return ("ciao anonimo, come stai? Sei timido?")
}
if (length(nomi)==1) {
messaggio <- paste ("ciao ", nomi[1], ", come stai?",
sep="")
return (messaggio)
}
messaggio <- "ciao "
if (length(nomi)<4) {
for (nome in nomi) {
messaggio <- paste(messaggio, nome, ", ", sep="")
}
} else {
messaggio <- paste(messaggio, "a tutti, ", sep="")
}
messaggio <- paste(messaggio, "come state?", sep="")
return (messaggio)
}
ciaoDipende(c("Giovanna", "Barbara"))
[1] "ciao Giovanna, Barbara, come state?"
ciaoDipende(c("Giovanna", "Barbara",
"Enrico", "Tommaso", "Gianluca"))
[1] "ciao a tutti, come state?"
ciaoDipende()
[1] "ciao anonimo, come stai? Sei timido?"
ciaoDipende("Enrico")
[1] "ciao Enrico, come stai?"
Funzioni
nomeFunzione <- function (argomento1=default, argomento2) {
# corpo della funzione
return(valore) # valore da sostituire
}
Funzione, corpo, argomenti
# il corpo della funzione
body(ciaoNomi)
{
messaggio <- "ciao "
for (nome in nomi) {
messaggio <- paste(messaggio, nome, ", ", sep = "")
}
messaggio <- paste(messaggio, "come state?", sep = "")
return(messaggio)
}
# gli argomenti della funzione
formals(ciaoNomi)
$nomi
c()
If
if (condizioneLogica) {
# se la condizione è vera,
# esegui il codice fra le parentesi
} else if (secondaCondizione) { # facoltativo
# se la prima è falsa ma la seconda è vera
# esegui la seconda
} else { # facoltativo
# se le condizioni precedenti sono tutte false,
# esegui invece questo codice
}
For
for (elemento in vettore) { # o sequenza
# esegui questo codice
# per ognuno degli elementi
}
Altre strutture di controllo
while: esegue un loop finché la condizione è vera
break: interrompe un loop (for, while, repeat)
repeat: loop infinito (è necessario interromperlo con un break)
next: passa alla iterazione successiva del loop
Esercizi
La media
Creare la funzione media(vettore)
senza usare le funzioni mean()
e sum()
.
Test:
vettore1 <- sample(1:10,20, replace = TRUE)
media(vettore1)
[1] 6.7
mean(vettore1)
[1] 6.7
Selezione
Creare la funzione seleziona(vettore, filtro)
senza usare il selettore vettore[filtro]
.
[1] 1 3 7 8
Error in seleziona(vettore2, vFiltro): non trovo la funzione "seleziona"
Sequenza
Creare la funzione sequenza(inizio,fine)
senza usare la funzione seq()
né inizio:fine
.
Test
seq(7,12)
[1] 7 8 9 10 11 12
sequenza(7,12)
[1] 7 8 9 10 11 12
Lancio di dadi
Creare la funzione lancio (numDadi) che simula il lancio di numDadi
dadi e la somma del loro risultato
Test
lancio(1)
[1] 2
lancio(1)
[1] 1
lancio(2)
[1] 4
lancio(2)
[1] 7
lancio(3)
[1] 7
Simulare mille lanci di un dado (salvando i risultati in lanci1
), e mille lanci di due dadi (salvando i risultati in lanci2
)
Creare un file in rMarkdown (es dadi.Rmd), inserire i chunk relativi alla funzione dati e allo script dei lanci, con una breve descrizione dei due passaggi.
Usando ggplot2, mostrare gli istogrammi dei due vettori lanci1
e lanci2
ed aggiungerli al file rMarkdown.
Minimo e massimo
Creare la funzione minmax
che restituisce un vettore con i valori minimo e massimo di un vettore, senza usare min
e max
vettore3 <- sample(1:1000,20,TRUE)
min(vettore3)
[1] 35
max(vettore3)
[1] 995
minmax(vettore3)
[1] 35 995
Rovesciare un vettore
Creare la funzione gira
che, dato un vettore, lo gira, senza usare la funzione rev()
.
vettore4 <- sample(1:100,10,TRUE)
vettore4
[1] 19 72 86 56 10 55 76 78 90 85
rev(vettore4)
[1] 85 90 78 76 55 10 56 86 72 19
gira(vettore4)
[1] 85 90 78 76 55 10 56 86 72 19
Riprodurre la funzione any
Creare la funzione tutti(vettore)
la funzione all()
senza, ovviamente, usare la funzione all()
vero <- rep(TRUE,5)
vero
[1] TRUE TRUE TRUE TRUE TRUE
all(vero)
[1] TRUE
tutti(vero)
[1] TRUE
misto <- sample(c(TRUE,FALSE),5,replace = TRUE)
misto
[1] TRUE TRUE TRUE TRUE FALSE
all(misto)
[1] FALSE
tutti(misto)
[1] FALSE