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()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.

plot of chunk prog--lanci_his

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

Cookies

Questo sito utilizza cookies tecnici e di terze parti quali google analytics per funzionalità tecniche e statistiche.

Se non acconsenti all'utilizzo dei cookie di terze parti, alcune di queste funzionalità potrebbero essere non disponibili.