6 Funzioni e Librerie
In R, è possibile trovare una grandissima quantità di funzioni matematiche, probabilistiche e statistiche. Non sarà perciò possibile affrontarle tutte in questo corso.
6.1 Le funzioni
Usare una funzione è piuttosto semplice. Basta scrivere il nome della funzione e poi i gli oggetti su cui applicarla tra parentesi tonde:
round(3.1415)
## [1] 3
factorial(3) #3!
## [1] 6
Gli oggetti che passiamo nella funzione sono chiamati argomenti. Un argomento può essere un dato grezzo, un oggetto di R o, addirittura il risultato di un’altra funzione.
In quest ultimo caso, R risolverà prima la funzione interna e poi quella esterna.
mean(1:6)
## [1] 3.5
mean(valore)
## [1] 6
round(mean(valore)) # prima mean e poi round
## [1] 6
Per estrarre casualmente una carta dal nostro mazzo possiamo usare la funzione sample()
.
La funzione sample()
ha 2 argomenti obbligatori: un vettore chiamato x
e un numero chiamato size
. sample(x,size)
ritonerà un vettore di size
elementi campionati da x
. Ad esempio:
sample(x = 1:4, size = 2)
## [1] 3 4
Per estrarre una carta casualmente impostiamo la seguente funzione:
<- deck[sample(x = 1 : dim(deck)[1], size = 1), ] #dim(deck)[1] è il numero di righe di deck, equivalente a nrow(deck) carta
Molte funzioni richiedono diversi argomenti, ogni argomento stabilisce una precisa variante della funzione. Gli argomenti vanno separati dalle virgole.
In R tutti gli argomenti hanno un nome (sono tutte keyword). Per specificare il valore di un argomento si usa l’operatore =
come fatto nel precedente script. L’ordine degli argomenti non conta se si usano i loro nomi.
Tuttavia, se si segue l’ordine degli argomenti, non è obbligatorio specificare il nome di un argomento, di solito il primo argomento viene inserito senza nome:
sample(1 : dim(deck)[1], size = 1)
## [1] 19
Cosa succede se si definisce il valore di un argomento che non esiste?
round(3.1415, corners = 2)
## Error in round(3.1415, corners = 2): unused argument (corners = 2)
Se non si è sicuri di quali argomenti passare alla funzione, si può usare la funzione args()
.
Ad esempio, possiamo vedere che la funzione round()
accetta 2 argomenti: x
e digits
:
args(round)
Si noti che con args()
è possibile vedere anche il valore di default dell’argomento.
Ad esempio il valore di default di digits
è 0. Quindi, se non definiamo un valore per questo argomento R arrotonderà alla prima cifra unitaria (0 decimali).
Con args()
è possibile vedere anche l’ordinamento degli argomenti. Qualora si decida di non nominare un argomento è necessario rispettarne l’ordine. Nel caso contrario possono apparire nell’ordine che si preferisce.
Ad esempio:
sample(1 : nrow(deck), 1) # = sample(1 : nrow(deck), size = 1)
## [1] 10
sample(size = 1, x = 1 : nrow(deck)) # se nomino gli argomenti posso decidere l'ordine che voglio
## [1] 47
6.1.1 Estraiamo una carta con reintroduzione
Di default, sample()
campiona senza reintroduzione, vale a dire che l’argomento replace
è uguale a FALSE
, se non diversamente specificato. Proviamo ad esempio a estrarre 53 carte dal nostro mazzo.
sample(1 : nrow(deck), size = 53)
## Error in sample.int(length(x), size, replace, prob): cannot take a sample larger than the population when 'replace = FALSE'
Estrarre senza reintroduzione 53 carte da un mazzo di 52 carte non è possibile. Impostiamo l’argumento replace = FALSE
per permettere di campionare con reintroduzione.
sample(1 : nrow(deck), size = 53, replace = TRUE)
## [1] 35 13 42 1 16 4 15 25 39 16 28 10 43 24 6 49 37
## [18] 10 34 11 51 32 28 14 52 38 51 8 30 46 29 15 26 33
## [35] 38 50 17 36 4 5 32 31 49 27 46 47 12 8 27 14 46
## [52] 40 19
Abbiamo appena eseguito la nostra prima simulazione con R!
Esercizio 15
Creare un dado con 6 facce.
Simulare il lancio di 3 dadi attraverso la funzione sample()
.
Sommare il risultato ottenuto usando la funzione sum()
.
<- 1 : 6
dado <- sample(dado, size = 3, replace = TRUE)
lancio sum(lancio)
## [1] 14
Ora che sappiamo come estrarre una carta dal mazzo avremo bisogno di un oggetto che ogni volta che viene richiamato estragga una carta. Si può crare questo genere di oggetto scrivendo la propria funzione.
6.2 Scrivere una funzione
Ricapitolando, scrivendo le seguenti righe di codice possiamo estrarre una carta:
<- sample(1 : nrow(deck), size = 1, replace = TRUE) carta
Possiamo scrivere ogni volta questa linea di codice o possiamo creare una funzione che, una volta richiamata, svolga la stessa operazione.
Andremo a chiamare questa funzione estraiCarta()
.
6.2.1 Il costruttore function
Ogni funzione in R è costituita da tre parti fondamentali: un nome, un corpo (il codice) e un set di argomenti.
Per creare la nostra funzione dobbiamo scrivere queste tre parti e salvarle in un oggetto di R. Questa operazione può essere svolta tramite il costruttore function
nel seguente modo:
<- function() {
myFunction #corpo
}
function
costruirà una funzione a partire dal codice (corpo) che verrà inserito all’interno delle parentesi graffe. Ad esempio, possiamo inserire il nostro codice per estrarre una carta all’interno della funzione estraiCarta()
:
<- function(mazzo) {
estraiCarta <- sample(1 : nrow(mazzo), size = 1, replace = TRUE)
riga
mazzo[riga, ] }
Si noti che la funzione avrà bisogno di un argomento, che nel nostro caso sarà un dataframe di carte. Abbiamo chiamato il primo argomento di estraiCarta mazzo
.
Per usare la funzione basta richiamarla:
estraiCarta(mazzo = deck) # equivalente a estraiCarta(deck)
## figura seme valore id
## 20 sette fiori 7 20
Ogni volta che la funzione viene richiamata, una nuova carta verrà campionata dal mazzo. Se si richiama la funzione senza le parentesi tonde, R vi stamperà nella console il suo contenuto:
estraiCarta
## function(mazzo) {
## riga <- sample(1 : nrow(mazzo), size = 1, replace = TRUE)
## mazzo[riga, ]
## }
Nel corpo della funzione vanno indicate tutte le operazioni da svolgere. L’ultima linea corrisponde al valore da ritornare in output, si può usare anche il comando return(risultato)
, oppure non produrre nessun risultato:
<- function(mazzo) { #uguale a prima ma uso return()
estraiCarta <- sample(1 : nrow(mazzo), size = 1, replace = TRUE)
riga return(mazzo[riga, ])
}
<- function(mazzo) { #nessun risultato
estraiCartaNoOutput <- sample(1 : nrow(mazzo), size = 1, replace = TRUE)
riga <- mazzo[riga, ]
cartaEstratta
}estraiCartaNoOutput(mazzo)
## Error in nrow(mazzo): oggetto "mazzo" non trovato
6.3 Ambiente locale e globale
Tutti gli oggetti creati all’interno di una funzione (ambiente locale) non vengono salvati nel Global Environment (ambiente globale) percui non possono essere richiamati al di fuori della funzione.
cartaEstratta
## Error in eval(expr, envir, enclos): oggetto "cartaEstratta" non trovato
Allo stesso tempo, tutti gli oggetti richiamati all’interno della funzione (ambiente locale) devono essere stati creati all’interno della funzione oppure devono essere stati passati attraverso gli argomenti.
Ad esempio, vediamo cosa succede se si crea una funzione che usa l’oggetto deck
ma quest ultimo non viene passato attraverso gli argomenti:
<- function() {
myFunction head(deck)
#fin qui nessun errore
} myFunction() #errore?
## figura seme valore id
## 1 re picche 13 1
## 2 regina picche 12 2
## 3 jack picche 11 3
## 4 dieci picche 10 4
## 5 nove picche 9 5
## 6 otto picche 8 6
E invece no! R non produce un errore in questo caso poichè l’oggetto deck
si trova nell’ambiente globale che è superiore all’ambiente locale. R esegue una ricerca seguendo un ordine gerarchico degli ambienti: prima cercherà l’oggetto all’interno dell’ambiente locale, se non lo trova, va a esaminare l’ambiente superiore (in questo caso l’ambiente globale) fino a che non raggiunge l’ambiente globale. Se non trova l’oggetto nell’ambiente globale ritorna un errore.
Ricapitolando, all’interno di ogni ambiente si possono utilizzare solo oggetti creati nell’ambiente stesso o negli ambienti superiori. Per poter usare oggetti provenienti da ambienti inferiori o dello stesso livello questi devono essere stati passati attraverso gli argomenti o attraverso la funzione return()
.
6.4 Argomenti
Possiamo dare alla nostra funzione quanti argomenti vogliamo. Basta separare i nomi degli argomenti da delle virgole quando creiamo la funzione.
Abbiamo inoltre visto che un argomento può avere un valore di default, come faccio a impostarlo?
Per rispondere a questa domanda proviamo a creare una funzione che estragga dal nostro mazzo un numero di carte nCarte
definito dall’utente, di default la funzione estrarrà 2 carte:
<- function(mazzo, nCarte = 2) { # estrae 2 carte se non diversamente specificato
estraiCarte <- sample(1 : nrow(mazzo), size = nCarte, replace = TRUE)
righe return(mazzo[righe, ])
}estraiCarte(deck) #estrae 2 carte
## figura seme valore id
## 50 tre cuori 3 50
## 14 re fiori 13 14
estraiCarte(deck, nCarte = 3) #estrae 3 carte
## figura seme valore id
## 51 due cuori 2 51
## 9 cinque picche 5 9
## 42 jack cuori 11 42
Esercizio 16
Creare una funzione che mischi le carte del mazzo deck
e dia come risultato il mazzo mischiato.
<- function(mazzo) { # estrae 5 carte se non diversamente specificato
shuffle <- sample(1 : nrow(mazzo), size = nrow(mazzo), replace = FALSE)
righe return(mazzo[righe, ])
}<- shuffle(deck)
shuffledDeck head(deck)
## figura seme valore id
## 1 re picche 13 1
## 2 regina picche 12 2
## 3 jack picche 11 3
## 4 dieci picche 10 4
## 5 nove picche 9 5
## 6 otto picche 8 6
head(shuffledDeck)
## figura seme valore id
## 51 due cuori 2 51
## 1 re picche 13 1
## 3 jack picche 11 3
## 31 nove quadri 9 31
## 44 nove cuori 9 44
## 48 cinque cuori 5 48
6.5 Librerie (packages)
Molte delle funzioni statistiche di R non vengono installate con R o RStudio ma risiedono in dei pacchetti o librerie (packages) che possono essere installati “on top”.
Per installare un pacchetto basta usare la funzione seguente:
install.packages("<nome pacchetto>")
Un pacchetto non è altro che un insieme di file (script di R e altro) che vengono salvati nella cartella “R-ver/win-library” quando vengono installati. Perciò non è necessario eseguire il comando precedente ogni volta che si vuole usare un pacchetto già installato.
Per usare il pacchetto (e le funzioni al suo interno) bisogna “caricare” il pacchetto attraverso la funzione:
library(<nome pacchetto>)
Notare che questa volta non sono necessarie le virgolette per richiamare il pacchetto. Infatti, una volta installato, un pacchetto diventa un oggetto di R.
Per avere delle informazioni su un pacchetto è possibile scaricare la sua documentazione cercando su google “documentation <nome pacchetto>”. Altrimenti, in R si può digitare il comando:
help(package = "<nome pacchetto>")
La funzione help()
può essere usata anche per leggere la documentazione relativa a una funzione. Ad esempio:
help(mean) # mean() serve a calcolare la media
#or
?mean

Figure 6.1: help(mean)
La documentazione relativa a una funzione contiene 6 componenti principali: Description, Usage, Arguments, Details, Value e Examples.
- Nella Description vi è una descrizione sintetica della funzione.
- L’Usage contiene i metodi della funzione, vale a dire le diverse implementazioni della funzione, in questo caso,
mean()
può essere usata con un solo argomento (x
) oppure specificando anche gli argomentitrim
ena.rm
. - Nella sezione Arguments sono descritti tutti gli argomenti personalizzabili della funzione. Nelle prime parole di ogni argomento troviamo il tipo di oggetto che può assumere. Ad esempio,
trim
può essere un valore compreso tra 0 e 0.5. - In Details troviamo i dettagli tecnici della funzione come le tipologie di metodologie implementate o come sono strutturati gli oggetti dati in input. In
mean()
questa sezione è mancante perchè non necessaria. - Il Value è l’oggetto che ritorna la funzione, cioè quello che compare nel
return()
. A volte, un oggetto in output può essere molto complesso e necessita di una descrizione dettagliata. - In Examples vi sono svariati esempi di utilizzo della funzione, molto utili a capire come usarla nella pratica.
Esercizio 17
- Quanti argomenti ha la funzione
quantile()
? - Quanti elementi ha l’oggetto ritornato dalla funzione
quantile()
? - Che valori può assumere il vettore
probs
? - Spiegare cosa succede se inserisco come argomento
probs = c(NA, 0.2, 0.5)
. - A che cosa serve la funzione
lm()
? - Quali caratteristiche dell’oggetto in output saranno mancanti se imposto
qr = FALSE
? - Com’è strutturato l’oggetto in output? Di che classe di oggetti fa parte?
- 5
- Tanti quanti la lunghezza di
probs
. Uno per quantile calcolato. - Può essere uguale a un vettore numerico con valori compresi tra 0 e 1.
- “NA and NaN values in probs are propagated to the result.” significa che se inserisco un NA al posto di un valore [0,1] in probs, la funzione ritornerà un NA nella posizione corrispondente. Nel nostro caso avremmo un vettore di 3 elementi che come primo elemento ha un NA.
- Serve per stimare modelli lineari (e non solo stimare).
- Nell’oggetto in uscita non verrà ritornata la scomposizione QR.
- Fa parte della classe apposita “lm” e contiene numerose caratteristiche del modello, dai dati in entrata (x,y,…) alle stime (coefficients), dalle impostazioni (weights, model,…) ai residui (residuals).
:::