Slide dall'Università degli Studi della Tuscia su Informatica. Il Pdf illustra i principi di programmazione e analisi dati in linguaggio R, con un focus sulle funzioni e la programmazione iterativa. Questo documento è utile per gli studenti universitari di Informatica.
Mostra di più59 pagine
Visualizza gratis il Pdf completo
Registrati per accedere all’intero documento e trasformarlo con l’AI.
Dipartimento di Scienze Ecologiche e Biologiche
Possiamo pensare alle funzioni in R in modo analogo alle classiche funzioni matematiche. Dati dei valori in input, le funzioni eseguono specifici calcoli e restituiscono in output il risultato ottenuto.
Input x = 2 y = 6
Funzione Output 8 f(x,y) = 4x - 2y + 10
Il comando usato per creare una funzione in R è function() seguito da una coppia di parentesi graffe { } al cui interno deve essere specificato il corpo della funzione:
nome_funzione <- function( ) { }
Nota come sia necessario assegnare la funzione ad un oggetto, ad esempio my_function, che diventerà il nome della nostra funzione. Per eseguire la funzione sarà sufficiente, come per ogni altra funzione, indicare il nome della funzione seguito dalle parentesi tonde, nel nostro caso my_function().
Vediamo alcuni esempi di semplici funzioni:
# Definisco la funzione my_greetings <- function(){ print ("Hello World!") }
my_greetings () ## [1] "Hello World!"
Quando chiamiamo la nostra funzione, R eseguirà il corpo della funzione e ci restituirà il risultato dell'ultimo comando eseguito.
Le funzioni del precedente esempio, tuttavia, si rivelano poco utili poiché eseguono sempre le stesse operazioni senza che ci sia permesso di specificare gli input delle funzioni. Inoltre, sebbene siano funzioni molto semplici, potrebbe non risultare chiaro quale sia effettivamente l'output restituito dalla funzione.
# Definisco un'altra funzione my_sum <- function () { X <- 7 y <- 3 x + y }
my_sum() ## [1] 10
Ricordiamo che in generale le funzioni, ricevuti degli oggetti in input, compiono determinate azioni e restituiscono dei nuovi oggetti in output.
Input e output sono quindi due aspetti fondamentali di ogni funzione che richiedono particolare attenzione.
Input - vengono specificati attraverso gli argomenti di una funzione. Per definire gli argomenti di una funzione, questi devono essere indicati all'interno delle parentesi tonde al momento della creazione della funzione
Output - Per specificare l'output di una funzione si utilizza la funzione return(), indicando tra le parentesi il nome dell'oggetto che si desidera restituire come risultato della funzione.
La definizione di una funzione con tutti i suoi elementi seguirà quindi il seguente schema:
nome_funzione <- function (argument_1, argument_2, ... ) { return () }
Possiamo ora riscrivere le precedenti funzioni permettendo di personalizzare gli input e evidenziando quale sia output che viene restituito.
# Ridefinisco my_greetings () my_greetings <- function (name) { greetings <- paste0("Hello ", name, " !") return (greetings) }
my_greetings ( name = "Bruno" ) ## [1] "Hello Bruno!"
# Ridefinisco my_sum() my_sum <- function(x, y) { result <- x + y return ( result) }
my_sum(x = 8, y = 6) ## [1] 14
Le funzioni sono sicuramente l'aspetto più utile e avanzato del linguaggio R e in generale dei linguaggi di programmazione.
I pacchetti che sono sviluppati in R non sono altro che insieme di funzioni che lavorano assieme per uno scopo preciso.
Oltre allo scopo della funzione è importante capire come gestire gli errori e gli imprevisti. Se la funzione infatti accetta degli argomenti, l'utente finale o noi stessi che la utilizziamo possiamo erroneamente usarla nel modo sbagliato.
E' importante quindi capire come leggere gli errori ma sopratutto creare messaggi di errore o di avvertimento utili per l'utilizzo della funzione.
Prendiamo ad esempio la funzione somma +, anche se non sembra infatti l'operatore + è in realtà una funzione. Se volessimo scriverlo come una funzione simile a quelle viste in precedenza possiamo:
my_sum <- function(x, y) { res <- x + y return (res) }
my_sum(1, 5) ## [1] 6
Abbiamo definito una (abbastanza inutile) funzione per calcolare la somma tra due numeri. Cosa succede se proviamo a sommare un numero con una stringa? Ovviamente è un'operazione che non ha senso e ci aspettiamo un qualche tipo di errore:
my_sum("pino", 5) ## Error in x + y: non-numeric argument to binary operator
Il concetto di ambiente in R è abbastanza complesso.
In parole semplici, tutte le operazioni che normalmente eseguiamo nella console o in uno script, avvengono in quello che si chiama global environment.
Quando scriviamo ed eseguiamo una funzione, stiamo creando un oggetto funzione (nel global environment) che a sua volta crea un ambiente interno per eseguire le operazioni previste.
Immaginiamo di avere questa funzione my_fun() che riceve un valore x e lo somma ad un valore y che non è un argomento:
my_fun <- function (x) { return (x + y) }
my_fun (10) ## Error in my_fun(10) : object 'y' not found-
my_fun <- function(x) { f(add == TRUE) return (x + y) }
my_fun (10) ## Error in my_fun(10) : object 'y' not found
Chiaramente otteniamo un errore perché l'oggetto y non è stato creato. Se però creiamo l'oggetto y all'interno della funzione, questa esegue regolarmente la somma MA non crea l'oggetto y nell'ambiente globale.
my_fun <- function (x) { y <- 1 return(x + y) }
my_fun (10)
Altra cosa importante, sopratutto per gestire effetti collaterali riguarda il fatto che la funzione NON modifica gli oggetti presenti nell'ambiente globale:
y <- 10 # ambiente globale my_fun <- function (x) { y <- 1 # ambiente funzione ientati return(x + y) # questo si basa su y funzione }
Come vedete, abbiamo creato un oggetto y dentro la funzione. Se eseguito nello stesso ambiente questo avrebbe sovrascritto il precedente valore. Il risultato si basa sul valore di y creato nell'ambiente funzione e l'y globale non è stato modificato.
my_fun (1) ## [1] 2 y ## [1] 10
Un ultimo punto importante riguarda invece il legame tra ambiente funzione e quello globale.
Abbiamo visto la loro indipendenza che però non è totale.
Se infatti all'interno della funzione utilizziamo una variabile definita solamente nell'ambiente globale, la funzione in automatico userà quel valore (se non specificato internamente) .
Questo è utile per far lavorare funzioni e variabili globali MA è sempre preferibile creare un ambiente funzione indipendente e fornire come argomenti tutte gli oggetti necessari.
y <- 10 my_fun <- function (x) { return(x + y) # viene utilizzato y globale }
Le cose importanti da ricordare quando si definiscono e utilizzano funzioni sono: