R — fondamenti del linguaggio

R è un linguaggio e ambiente per il calcolo statistico e la produzione di grafici, sviluppato per l'analisi dei dati. È interpretato, orientato ai vettori e dispone di un vastissimo ecosistema di pacchetti (CRAN, Bioconductor).

1. Fondamenti

Assegnazione e operazioni di base

In R l'operatore di assegnazione idiomatico è <- (funziona anche =).

x <- 5
y = 3
z <- x + y # 8

# Operazioni aritmetiche
7 %/% 2 # divisione intera -> 3
7 %% 2 # modulo -> 1
2^10 # potenza -> 1024

Tipi di dato principali

R possiede quattro tipi atomici fondamentali: numeric (double), integer, character, logical, oltre a complex.

n <- 3.14 # numeric
i <- 5L # integer (suffisso L)
s <- "ciao" # character
b <- TRUE # logical
cx <- 2 + 3i # complex

class(n) # "numeric"
typeof(i) # "integer"
is.character(s) # TRUE

Un concetto peculiare di R è NA (dato mancante), distinto da NULL (assenza di oggetto) e NaN (Not a Number).

2. Strutture dati

Vettori

Il vettore è la struttura fondamentale: R è "vettorializzato", cioè le operazioni si applicano elemento per elemento.

v <- c(2, 4, 6, 8, 10)
v * 2 # 4 8 12 16 20
v[2] # 4  (indicizzazione da 1!)
v[c(1, 3)] # 2 6
v[v > 5] # 6 8 10 (indicizzazione logica)
seq(0, 1, by = 0.25)
rep(c(1, 2), times = 3)

Nota: in R gli indici partono da 1, non da 0.

Matrici

M <- matrix(1:6, nrow = 2, ncol = 3)
M %*% t(M) # prodotto matriciale
solve(A) # inversa di A
dim(M) # 2 3

Il prodotto matriciale $C = A B$ ha elementi:

\[c_{ij} = \sum_{k=1}^{n} a_{ik}\, b_{kj}\]

Liste e data frame

La lista può contenere elementi eterogenei; il data.frame è la struttura tabellare per eccellenza (colonne di tipi diversi, stessa lunghezza).

lst <- list(nome = "Anna", eta = 30, voti = c(28, 30, 25))
lst$voti # accesso per nome

df <- data.frame(
    nome = c("Anna", "Bruno"),
    eta = c(30, 25),
    stringsAsFactors = FALSE
)
df$eta # colonna
df[df$eta > 26, ] # filtro per riga
str(df) # struttura

3. Controllo di flusso e funzioni

# Condizioni
if (x > 0) {
    print("positivo")
} else {
    print("non positivo")
}

# Cicli
for (i in 1:5) print(i^2)

while (x > 0) x <- x - 1

# Definizione di funzione
media_geom <- function(x) {
    exp(mean(log(x)))
}
media_geom(c(1, 4, 16)) # 4

La media geometrica calcolata sopra corrisponde a:

\[G = \left( \prod_{i=1}^{n} x_i \right)^{1/n} = \exp\!\left( \frac{1}{n} \sum_{i=1}^{n} \ln x_i \right)\]

La famiglia apply

Al posto dei cicli espliciti, R predilige funzioni di ordine superiore.

sapply(1:5, function(k) k^2) # vettore: 1 4 9 16 25
lapply(1:3, sqrt) # lista
apply(M, 1, sum) # somma per riga (MARGIN = 1)
vapply(x, is.numeric, logical(1)) # con tipo di ritorno specificato

4. Statistica descrittiva

R nasce per la statistica; le funzioni di base sono immediate.

x <- c(4, 8, 15, 16, 23, 42)
mean(x) # media
median(x) # mediana
sd(x) # deviazione standard campionaria
var(x) # varianza
quantile(x) # quartili
summary(x) # riepilogo completo

Media aritmetica:

\[\bar{x} = \frac{1}{n} \sum_{i=1}^{n} x_i\]

Varianza campionaria (denominatore $n-1$, correzione di Bessel):

\[s^2 = \frac{1}{n-1} \sum_{i=1}^{n} (x_i - \bar{x})^2\]

Coefficiente di correlazione di Pearson:

\[r_{xy} = \frac{\displaystyle\sum_{i=1}^{n} (x_i - \bar{x})(y_i - \bar{y})} {\sqrt{\displaystyle\sum_{i=1}^{n} (x_i - \bar{x})^2}\;\sqrt{\displaystyle\sum_{i=1}^{n} (y_i - \bar{y})^2}}\]
cor(x, y) # correlazione di Pearson
cor(x, y, method = "spearman")

5. Distribuzioni di probabilità

Per ogni distribuzione R offre quattro funzioni con prefissi d, p, q, r (densità, ripartizione, quantile, generazione casuale).

dnorm(0) # densità della normale in 0
pnorm(1.96) # P(Z <= 1.96) ~ 0.975
qnorm(0.975) # quantile ~ 1.96
rnorm(100, mean = 0, sd = 1) # 100 valori casuali

La densità della distribuzione normale $\mathcal{N}(\mu, \sigma^2)$ è:

\[f(x) = \frac{1}{\sigma \sqrt{2\pi}} \, \exp\!\left( -\frac{(x - \mu)^2}{2\sigma^2} \right)\]

Altre distribuzioni comuni: binom, pois, unif, exp, t, chisq, f.

6. Regressione lineare

Il modello lineare è uno strumento centrale in R, gestito da lm().

Il modello di regressione multipla si scrive:

\[y_i = \beta_0 + \beta_1 x_{i1} + \dots + \beta_p x_{ip} + \varepsilon_i, \qquad \varepsilon_i \sim \mathcal{N}(0, \sigma^2)\]

La stima ai minimi quadrati ordinari (OLS) in forma matriciale è:

\[\hat{\boldsymbol{\beta}} = (\mathbf{X}^\top \mathbf{X})^{-1} \mathbf{X}^\top \mathbf{y}\]
modello <- lm(mpg ~ wt + hp, data = mtcars)
summary(modello) # coefficienti, R^2, p-value
coef(modello) # stime beta
predict(modello, newdata = data.frame(wt = 3, hp = 120))
residuals(modello)
confint(modello) # intervalli di confidenza

Il coefficiente di determinazione misura la bontà di adattamento:

\[R^2 = 1 - \frac{\sum_{i=1}^{n} (y_i - \hat{y}_i)^2}{\sum_{i=1}^{n} (y_i - \bar{y})^2}\]

7. Grafici

R dispone di un sistema grafico "base" e del pacchetto ggplot2 (grammar of graphics).

# Grafica base
plot(
    mtcars$wt,
    mtcars$mpg,
    xlab = "Peso",
    ylab = "Consumo",
    main = "Consumo vs Peso",
    pch = 19
)
abline(lm(mpg ~ wt, data = mtcars), col = "red")
hist(mtcars$mpg, breaks = 10)
boxplot(mpg ~ cyl, data = mtcars)
# ggplot2
library(ggplot2)
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
    geom_point(size = 2) +
    geom_smooth(method = "lm", se = TRUE) +
    labs(title = "Consumo vs Peso", color = "Cilindri") +
    theme_minimal()

8. L'ecosistema tidyverse

Il tidyverse è una raccolta di pacchetti per la manipolazione moderna dei dati. L'operatore pipe |> (nativo da R 4.1) o %>% (magrittr) concatena le operazioni.

library(dplyr)

mtcars |>
    filter(cyl == 6) |>
    group_by(gear) |>
    summarise(
        consumo_medio = mean(mpg),
        n = n()
    ) |>
    arrange(desc(consumo_medio))

Verbi principali di dplyr: filter() (righe), select() (colonne), mutate() (nuove colonne), group_by() + summarise() (aggregazione), arrange() (ordinamento), join (unione tabelle).

9. Gestione dei pacchetti

install.packages("ggplot2") # installazione da CRAN
library(ggplot2) # caricamento
require(ggplot2) # come library ma ritorna TRUE/FALSE
update.packages() # aggiornamento

# Import/export dati
df <- read.csv("dati.csv")
write.csv(df, "output.csv", row.names = FALSE)
readRDS("oggetto.rds") # formato binario nativo

10. Riferimenti rapidi

Operazione Funzione
Aiuto su una funzione ?nome oppure help(nome)
Struttura di un oggetto str(x)
Ambiente / variabili ls()
Rimuovere una variabile rm(x)
Lunghezza / dimensioni length(), dim(), nrow(), ncol()
Valori mancanti is.na(), na.omit(), complete.cases()
Applicare una funzione sapply, lapply, apply, Map, Reduce

11. Documentazione e risorse

Nota sulla versione: gli esempi fanno riferimento alla serie corrente di R. Verifica sempre la versione installata con R.version.string e consulta la documentazione dei pacchetti utilizzati.