Linguaggio di programmazione R: tutorial per muovere i primi passi

R è un noto linguaggio di programmazione, utilizzato principalmente per eseguire calcoli statistici nel campo delle scienze e della matematica. È un linguaggio interessante con delle caratteristiche molto peculiari. Una volta acquistata familiarità con la sintassi, lavorarci diventa molto gradevole.

Quali sono le principali caratteristiche del linguaggio di programmazione R?

R non è un linguaggio di programmazione “general-purpose” come possono essere Java o Python. Al contrario, viene usato nell’ambito dello statistical computing, in italiano “calcolo statistico”. Nonostante la massiccia concorrenza in questo settore, R si situa da anni fra i 20 linguaggi di programmazione più popolari.

A rendere R così speciale non è solo il linguaggio in sé, ma tutto il contorno. Infatti, normalmente la sua programmazione avviene in un ambiente interattivo, completo di Read-Eval-Print Loop (REPL) e di supporto integrato. Questo linguaggio open source è supportato da un ecosistema molto sviluppato: il repository dei pacchetti “The Comprehensive R Archive Network” (CRAN) è gestito dalla community. Inoltre, questa fornisce in modo continuativo record di dati e white paper scientifici che illustrano nuovi approcci e mettono a disposizione nuovi pacchetti.

Insieme, queste caratteristiche fanno di R l’ambiente di programmazione perfetto per il calcolo statistico e la data science. Il suo carattere interattivo invita alla sperimentazione: consente un apprendimento giocoso del linguaggio e dei calcoli matematici che ne stanno alla base.

R è un linguaggio di programmazione specifico per la statistica e l’elaborazione di dati

R è un linguaggio di programmazione statistica e si basa su concetti come la distribuzione normale, i test statistici, i modelli e la regressione. Esistono alcuni linguaggi scientifici comparabili a R: oltre a Matlab ricordiamo Julia, un linguaggio abbastanza giovane, ma comunque degno di nota.

Negli ultimi anni, in ambito statistico si è affermato anche l’uso di Python. Ma, a differenza di questo, R dispone di un supporto nativo per la programmazione statistica. Opera sui valori in modo diverso dagli altri linguaggi: è questa la sua caratteristica di spicco. Solitamente sono disponibili più valori contemporaneamente, pertanto questo linguaggio tende a elaborare più dati alla volta. In R il valore più semplice è raramente un singolo numero.

Di seguito presentiamo un facile esempio che ci permetterà di esaminare da vicino come avviene l’elaborazione di dati in R. In ogni linguaggio di programmazione è possibile eseguire operazioni matematiche e lo stesso vale per R. Procediamo a sommare due numeri:


10 + 5
R

Fin qui nulla di speciale. In R è possibile applicare questa stessa operazione (addizione) a una serie di numeri. Raggruppiamo quindi due numeri in un elenco e aggiungiamo un valore costante:

# returns 15, 25
c(10, 20) + 5
R

Per programmatori e programmatrici con una certa esperienza si tratta senz’altro di un risultato sorprendente. Infatti, nemmeno Python in tutta la sua dinamicità e modernità consente questo tipo di calcolo:

# throws an error
[10, 20] + 5
R

Con R è addirittura possibile sommare due liste. A tal proposito gli elementi della lista non vengono uniti in una sola lista, ma si esegue l’operazione matematica appropriata per ciascun elemento:

# returns 42, 69
c(40, 60) + c(2, 9)
R

Nei linguaggi più tradizionali come Java o C++, per elaborare più elementi di una lista è necessario usare un ciclo. Infatti, questi linguaggi operano una netta distinzione fra componenti singoli (gli scalari) e le strutture di dati compositi (i vettori). Nel linguaggio di programmazione R, il vettore è considerato l’unità di base, mentre lo scalare sotto forma di vettore, composto da un solo elemento, è considerato un’eccezione.

Nella statistica la proverbiale precisione matematica tende a venire meno. Infatti, la statistica tiene in considerazione incertezze e dati imperfetti ricavati da un contesto reale. C’è sempre la possibilità che qualcosa non vada secondo i piani. Fortunatamente, R presenta una certa tolleranza agli errori. Ad esempio, è in grado di gestire i valori mancanti senza causare il crash di uno script.

Ora dimostriamo la solidità di questo linguaggio mediante un altro esempio. In linea di massima, dividendo un qualsiasi numero per zero in qualsiasi linguaggio di programmazione, si genererà un’eccezione con conseguente crash. In R non è così: qui una divisione per zero genera il valore Inf, consentendo in un secondo momento una facile pulizia dei dati, eseguita filtrando il valore.

# list of divisors, containing zero
divisors = c(2, 4, 0, 10)
# returns `c(50, 25, Inf, 10)`
quotients = 100 / divisors
# filter out Inf; returns `c(50, 25, 10)`
cleaned_quotients = quotients[quotients != Inf]
R

R supporta la programmazione orientata agli oggetti (OOP) e la programmazione funzionale

La programmazione con R è alquanto flessibile: risulta pertanto difficile inserire con chiarezza questo linguaggio nella gerarchia dei paradigmi di programmazione. Infatti, pur esistendo un sistema di OOP a sostegno di questo linguaggio, vengono completamente meno le classiche definizioni delle classi. Nell’uso quotidiano, in prima linea si usano approcci imperativi e di tipo funzionale. In particolare risultano molto ben definite le caratteristiche funzionali adatte all’elaborazione dei dati.

Come in JavaScript, questo sistema a oggetti spicca per la sua flessibilità. Le funzioni generiche sono comparabili a Python e possono essere applicate su oggetti di diverso tipo. Ad esempio, nella programmazione R esiste la funzione length(), simile a quella len() di Python.

Come funziona la programmazione R?

Nella programmazione R tutto ruota intorno ai dati poiché questi stanno alla base del calcolo statistico. Per sviluppare una soluzione a un problema in R, è necessario un record di dati. Purtroppo spesso tale record di dati non è ancora disponibile al momento dello sviluppo del codice. Pertanto, un progetto di programmazione in R spesso parte da una simulazione di dati. Scriviamo il codice, ne testiamo la funzionalità e in un secondo momento sostituiamo i dati di prova con dati reali.

Come si esegue il codice R?

Come Ruby o Python, R è un linguaggio di scripting dinamico e interpretato. Qui non esiste alcuna distinzione fra codice sorgente e codice eseguibile, a differenza del linguaggio di programmazione C. Lo sviluppo del codice avviene per la maggior parte in modo interattivo, ovvero l’interprete viene istruito, riga per riga, tramite il codice sorgente la cui esecuzione avviene immediatamente. Le variabili vengono create in automatico a seconda del bisogno, i nomi sono legati al tempo di esecuzione.

Usando questa programmazione interattiva e dinamica è come se ci si trovasse all’interno di un programma in esecuzione. È possibile esaminare e modificare gli oggetti già creati e allo stesso modo è possibile testare automaticamente nuove idee. Il comando help consente l’accesso alla documentazione di sintassi e funzioni:

# view help for `for` syntax
help('for')
# view help for `c()` function
help(c)
R

Dall’interprete è possibile caricare in modo dinamico file di script. Il comando source funziona allo stesso modo del comando shell, che si considera equivalente. Durante la chiamata si legge il contenuto del testo sorgente R, che viene inserito nella sessione in corso.

source('path/to/file.r')
R

Com’è la sintassi del linguaggio R?

Il linguaggio di scripting fa uso delle parentesi graffe usate in C e Java per delimitare i corpi da funzioni e istruzioni di controllo. Al contrario di Python, l’indentazione del codice non influisce sulla sua funzione. Come in Ruby e in Python, i commenti iniziano con un cancelletto; alla fine di un’istruzione è necessario il punto e virgola.

Con un po’ di esperienza è possibile riconoscere immediatamente il codice di R, perché il linguaggio presenta alcune peculiarità. Oltre a impiegare il segno uguale come operatore di assegnazione, la programmazione R fa uso anche di due operatori simili a una freccia -> e <-. In questo modo è possibile invertire la direzione dell’assegnamento:

# equivalent assignments
age <- 42
'Jack' -> name
person = c(age, name)
R

Un’ulteriore caratteristica del codice R è l’annotazione pseudo-oggetto secondo lo schema object.method():

# test if argument is a number
is.numeric(42)
R

Apparentemente, la funzione is.numeric sembra un metodo numeric() appartenente a un oggetto di nome is. Ma le cose in realtà stanno diversamente. Nella programmazione R, il punto è considerato un carattere regolare; pertanto la funzione si potrebbe scrivere anche is_numeric invece di is.numeric.

Per generare i vettori, importantissimi nella programmazione R, si fa ricorso alla funzione di concatenazione c():

people.ages <- c(42, 51, 69)
R

Se si applica la funzione ai vettori, questi vengono uniti in un vettore continuo.

# yields `c(1, 2, 3, 4)`
c(c(1, 2), c(3, 4))
R

A differenza della maggior parte dei linguaggi di programmazione, in R l’indicizzazione degli elementi di un vettore inizia da 1. Inizialmente può essere necessario abituarsi a questa peculiarità, ma questo aiuta a evitare i temuti errori logici di tipo off by one. L’indice più elevato di un vettore corrisponde alla lunghezza del vettore stesso:

# create a vector of names
people <- c('Jack', 'Jim', 'John')
# access the first name
people[1] == 'Jack'
# access the last name
people[length(people)] == 'John'
R

Come in Python, anche nella programmazione R ritroviamo il concetto di slicing. Con una slice è possibile indicizzare una porzione di un vettore. Questa si basa su sequenze che in R vengono supportate in modo nativo. Generiamo una sequenza di numeri e ne selezioniamo una porzione:

# create vector of numbers between 42 and 69
nums = seq(42, 69)
# equivalent assignment using sequence notation
nums = 42:69
# using a sequence, slice elements 3 through 7
sliced = nums[3:7]
R

Come funzionano le strutture di controllo nella programmazione R?

Le operazioni di base nella programmazione R sono appositamente definite per i vettori. In questo modo spesso non è necessario creare dei cicli, ma si esegue un’operazione direttamente sull’intero vettore, modificandone però i singoli elementi. Di seguito facciamo quadrare i primi dieci numeri positivi senza ciclo:

nums <- seq(10)
squares <- nums ** 2
squares[3] == 9
R

Quando si usa il ciclo for in R è necessario tenere in considerazione che questo non funziona come in C, Java o JavaScript. Infatti, l’iterazione viene eseguita direttamente sugli elementi come in Python, senza dover impiegare una variabile in sequenza:

people = c('Jim', 'Jack', 'John')
for (person in people) {
    print(paste('Here comes', person, sep = ' '))
}
R

Naturalmente la ramificazione if else in R esiste e viene usata come struttura di controllo di base. Tuttavia, in molti casi anche questa può essere sostituita da funzioni filtro o tramite l’indicizzazione logica di vettori. Creiamo un vettore con informazioni riguardanti l’età e filtriamo rispettivamente le persone maggiori di 18 anni mediante due variabili, senza dover usare alcun ciclo o ramificazione:

# create 20 ages between 1 and 99
ages = as.integer(runif(20, 1, 99))
# filter adults
adults = ages[ages > 18]
# filter children
children = ages[ages < 18]
# make sure everyone is accounted for
length(adults) + length(children) == length(ages)
R

Ora vi presentiamo invece l’approccio equivalente tramite strutture di controllo:

# create 20 ages between 1 and 99
ages = as.integer(runif(20, 1, 99))
# start with empty vectors
adults = c()
children = c()
# populate vectors
for (age in ages) {
    if (age > 18) {
        adults = c(adults, age)
    }
    else {
        children = c(children, age)
    }
}
R

Cosa serve per iniziare a programmare in R?

Per poter iniziare a programmare in R, è sufficiente installare l’apposito programma locale “installer”. Questo è disponibile gratuitamente e può essere scaricato nella maggior parte dei sistemi operativi. L’installazione standard di R comprende un interprete GUI con REPL, il supporto integrato e l’editor. Affinché la programmazione risulti produttiva, consigliamo di scegliere fra gli editor di codice più conosciuti. RStudio di Posit offre un’interessante alternativa all’ambiente R.

Per quali tipi di progetto è adatto R?

Spesso, la programmazione R trova ampio impiego nelle scienze e nella ricerca, ad esempio nella bioinformatica e nell’apprendimento automatico. Tuttavia, il linguaggio è adatto per tutti i progetti che si servono della modellazione statistica o dei modelli matematici. È invece meno adatto per processare testi: in questo caso Python risulta nettamente più indicato.

R può essere usato per sostituire i classici calcoli e le visualizzazioni normalmente contenute in fogli di calcolo. In questo modo i dati e il codice non vengono mescolati nelle celle, consentendo una migliore organizzazione e una chiara separazione delle attività. Basta scrivere il codice una sola volta: questo verrà quindi applicato a più record. Inoltre, non vi è alcun rischio di sovrascrivere la formula di una cella in caso di modifiche manuali.

Per le pubblicazioni scientifiche, R è considerato il sistema aureo dei linguaggi macchina: è proprio la suddivisione del codice dai dati a consentire la riproducibilità scientifica. Il sofisticato sistema di strumenti e pacchetti offerti da R consente di creare delle pipeline di pubblicazione più efficienti. Valutazioni e visualizzazioni si generano automaticamente da codice e dati, per poi essere integrate in documenti LaTeX o RMarkdown ben strutturati.

Consiglio

Partite da una base solida per il vostro sito web: acquistate lo spazio web a un prezzo vantaggioso su IONOS!

Per offrirti una migliore esperienza di navigazione online questo sito web usa dei cookie, propri e di terze parti. Continuando a navigare sul sito acconsenti all’utilizzo dei cookie. Scopri di più sull’uso dei cookie e sulla possibilità di modificarne le impostazioni o negare il consenso.