class: center, middle, inverse, title-slide # Programmazione ### Stefano Bussolon ### 03/2019 - 01/2020 --- # 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. ```r ciao <- function() { messaggio <- "ciao a tutti" return (messaggio) } ``` Invochiamo la funzione ```r ciao() ``` ``` [1] "ciao a tutti" ``` --- ### Passaggio di un argomento La versione seguente richiede un parametro (un nome) che verrà usato per personalizzare il saluto ```r ciaoNome <- function (nome) { messaggio <- paste("ciao ", nome, ", come stai?", sep="" ) return (messaggio) } ``` Se invochiamo la funzione senza il parametro, R segnalerà un errore. ```r ciaoNome("Francesco") ``` ``` [1] "ciao Francesco, come stai?" ``` ```r # 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. ```r ciaoNomeAmico <- function (nome="amico") { messaggio <- paste("ciao ", nome, ", come stai?", sep="" ) return (messaggio) } ``` ```r ciaoNomeAmico("Marika") ``` ``` [1] "ciao Marika, come stai?" ``` ```r 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. ```r ciaoNomeForse <- function (nome=NULL) { messaggio <- "" if(!is.null(nome)) { messaggio <- paste("ciao ", nome, ", come stai?", sep="" ) } else { messaggio <- "Ciao anonimo ;)" } return (messaggio) } ``` ```r ciaoNomeForse("Matteo") ``` ``` [1] "ciao Matteo, come stai?" ``` ```r ciaoNomeForse() ``` ``` [1] "Ciao anonimo ;)" ``` --- ### For In questa iterazione, gestiamo un vettore di più nomi, introducendo il ciclo `for`. ```r 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) } ``` --- ```r nomi <- c("Mario", "Antonella", "Lucia") ciaoNomi(nomi) ``` ``` [1] "ciao Mario, Antonella, Lucia, come state?" ``` ```r 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. --- ```r 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) } ``` --- ```r ciaoDipende(c("Giovanna", "Barbara")) ``` ``` [1] "ciao Giovanna, Barbara, come state?" ``` ```r ciaoDipende(c("Giovanna", "Barbara", "Enrico", "Tommaso", "Gianluca")) ``` ``` [1] "ciao a tutti, come state?" ``` ```r ciaoDipende() ``` ``` [1] "ciao anonimo, come stai? Sei timido?" ``` ```r ciaoDipende("Enrico") ``` ``` [1] "ciao Enrico, come stai?" ``` --- ## Funzioni ```r nomeFunzione <- function (argomento1, argomento2=default) { # corpo della funzione return(valore) # valore da sostituire } ``` --- ## Funzione, corpo, argomenti ```r # 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) } ``` ```r # gli argomenti della funzione formals(ciaoNomi) ``` ``` $nomi c() ``` --- ## If ```r 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 ```r 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: ```r vettore1 <- sample(1:10,20, replace = TRUE) media(vettore1) ``` ``` [1] 5.35 ``` ```r mean(vettore1) ``` ``` [1] 5.35 ``` --- ### Selezione Creare la funzione `seleziona(vettore, filtro)` senza usare il selettore `vettore[filtro]`. Test ```r vettore2 <- seq(10) vFiltro <- c(TRUE,FALSE,TRUE,FALSE,FALSE, FALSE,TRUE,TRUE,FALSE,FALSE) vettore2[vFiltro] ``` ``` [1] 1 3 7 8 ``` ```r seleziona(vettore2,vFiltro) ``` ``` [1] 1 3 7 8 ``` --- ### Sequenza Creare la funzione `sequenza(inizio,fine)` senza usare la funzione `seq()` né `inizio:fine`. Test ```r seq(7,12) ``` ``` [1] 7 8 9 10 11 12 ``` ```r 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 ```r lancio(1) ``` ``` [1] 4 ``` ```r lancio(1) ``` ``` [1] 5 ``` ```r lancio(2) ``` ``` [1] 4 ``` ```r lancio(2) ``` ``` [1] 7 ``` ```r lancio(3) ``` ``` [1] 13 ``` --- 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. --- ![](programmazione_files/figure-html/prog_lanci_his-1.png)<!-- --> --- Creare la funzione `minmax` che restituisce un vettore con i valori minimo e massimo di un vettore, senza usare `min` e `max` ```r vettore3 <- sample(1:1000,20,TRUE) min(vettore3) ``` ``` [1] 15 ``` ```r max(vettore3) ``` ``` [1] 974 ``` ```r minmax(vettore3) ``` ``` [1] 15 974 ``` --- ### Rovesciare un vettore Creare la funzione `gira` che, dato un vettore, lo gira, senza usare la funzione `rev()`. ```r vettore4 <- sample(1:100,10,TRUE) vettore4 ``` ``` [1] 85 28 100 95 97 22 46 73 67 79 ``` ```r rev(vettore4) ``` ``` [1] 79 67 73 46 22 97 95 100 28 85 ``` ```r gira(vettore4) ``` ``` [1] 79 67 73 46 22 97 95 100 28 85 ``` --- ### Riprodurre la funzione any Creare la funzione `tutti(vettore)` la funzione `all()` senza, ovviamente, usare la funzione `all()` ```r (vero <- rep(TRUE,5)) ``` ``` [1] TRUE TRUE TRUE TRUE TRUE ``` ```r all(vero) ``` ``` [1] TRUE ``` ```r tutti(vero) ``` ``` [1] TRUE ``` --- ```r (misto <- sample(c(TRUE,FALSE),5,replace = TRUE)) ``` ``` [1] FALSE FALSE FALSE FALSE TRUE ``` ```r all(misto) ``` ``` [1] FALSE ``` ```r tutti(misto) ``` ``` [1] TRUE ```