Ciclo for in R
Il ciclo for in R permette di eseguire un blocco di codice per ogni elemento di un vettore, una lista o qualsiasi oggetto iterabile. A differenza di linguaggi come C o Java, in R il ciclo for itera direttamente sugli elementi di una struttura dati, rendendo la sintassi più espressiva e vicina al linguaggio naturale.
Sintassi Base del Ciclo for
La struttura del ciclo for in R utilizza la parola chiave in per iterare sugli elementi:
# Iterare su un vettore di numeri
numeri <- c(10, 20, 30, 40, 50)
for (n in numeri) {
cat("Il valore è:", n, "\n")
}
# Il valore è: 10
# Il valore è: 20
# Il valore è: 30
# Il valore è: 40
# Il valore è: 50
# Iterare su un vettore di stringhe
frutti <- c("mela", "banana", "arancia")
for (frutto in frutti) {
cat("Mi piace la", frutto, "\n")
}
# Mi piace la mela
# Mi piace la banana
# Mi piace la arancia
Iterare con Indici: seq_along() e seq_len()
Quando serve accedere sia all’indice che al valore, si usano seq_along() o seq_len():
nomi <- c("Anna", "Bruno", "Carla", "Diego")
# seq_along() crea una sequenza di indici della stessa lunghezza del vettore
for (i in seq_along(nomi)) {
cat("Studente", i, ":", nomi[i], "\n")
}
# Studente 1 : Anna
# Studente 2 : Bruno
# Studente 3 : Carla
# Studente 4 : Diego
# seq_len() crea una sequenza da 1 a n
n <- 5
for (i in seq_len(n)) {
cat(i, "al quadrato fa", i^2, "\n")
}
# 1 al quadrato fa 1
# 2 al quadrato fa 4
# 3 al quadrato fa 9
# 4 al quadrato fa 16
# 5 al quadrato fa 25
# ATTENZIONE: evitare 1:length(x) se x potrebbe essere vuoto
# Se x è vuoto, 1:0 restituisce c(1, 0) causando errori
# seq_along() restituisce correttamente un vettore vuoto
x <- c()
for (i in seq_along(x)) {
print(i) # Non viene eseguito
}
Iterare su Liste
Le liste in R possono contenere elementi di tipi diversi. Il ciclo for itera su ogni elemento:
persona <- list(
nome = "Marco",
eta = 30,
hobby = c("lettura", "programmazione")
)
for (campo in names(persona)) {
cat(campo, ":", toString(persona[[campo]]), "\n")
}
# nome : Marco
# eta : 30
# hobby : lettura, programmazione
# Iterare su una lista di liste
studenti <- list(
list(nome = "Anna", voto = 28),
list(nome = "Bruno", voto = 24),
list(nome = "Carla", voto = 30)
)
for (s in studenti) {
cat(s$nome, "ha preso", s$voto, "\n")
}
# Anna ha preso 28
# Bruno ha preso 24
# Carla ha preso 30
Iterare su un Data Frame
Con i data frame si può iterare sulle righe o sulle colonne:
df <- data.frame(
prodotto = c("Pane", "Latte", "Uova"),
prezzo = c(1.50, 1.20, 2.80),
quantita = c(2, 3, 1)
)
# Iterare sulle righe
for (i in seq_len(nrow(df))) {
totale <- df$prezzo[i] * df$quantita[i]
cat(df$prodotto[i], "- Totale:", totale, "euro\n")
}
# Pane - Totale: 3 euro
# Latte - Totale: 3.6 euro
# Uova - Totale: 2.8 euro
# Iterare sulle colonne (ogni colonna è un vettore)
for (col in names(df)) {
cat("Colonna:", col, "- Tipo:", class(df[[col]]), "\n")
}
# Colonna: prodotto - Tipo: character
# Colonna: prezzo - Tipo: numeric
# Colonna: quantita - Tipo: numeric
next e break
Le istruzioni next e break permettono di controllare il flusso all’interno del ciclo:
# next: salta all'iterazione successiva (come continue in altri linguaggi)
for (i in 1:10) {
if (i %% 2 == 0) {
next # Salta i numeri pari
}
cat(i, "")
}
# 1 3 5 7 9
cat("\n")
# break: interrompe completamente il ciclo
for (i in 1:100) {
if (i > 5) {
break # Esce dal ciclo quando i supera 5
}
cat(i, "")
}
# 1 2 3 4 5
cat("\n")
# Esempio pratico: cercare un valore in un vettore
dati <- c(14, 7, 23, 42, 8, 15)
obiettivo <- 42
for (i in seq_along(dati)) {
if (dati[i] == obiettivo) {
cat("Trovato", obiettivo, "alla posizione", i, "\n")
break
}
}
# Trovato 42 alla posizione 4
Cicli Annidati
I cicli annidati sono utili per lavorare con strutture bidimensionali come matrici:
# Creare una tavola pitagorica 5x5
cat("Tavola pitagorica:\n")
for (i in 1:5) {
for (j in 1:5) {
cat(sprintf("%4d", i * j))
}
cat("\n")
}
# 1 2 3 4 5
# 2 4 6 8 10
# 3 6 9 12 15
# 4 8 12 16 20
# 5 10 15 20 25
# Popolare una matrice
matrice <- matrix(0, nrow = 3, ncol = 4)
for (i in 1:3) {
for (j in 1:4) {
matrice[i, j] <- i * 10 + j
}
}
print(matrice)
# [,1] [,2] [,3] [,4]
# [1,] 11 12 13 14
# [2,] 21 22 23 24
# [3,] 31 32 33 34
Accumulare Risultati in un Ciclo
Un uso comune del ciclo for consiste nell’accumulare risultati in un vettore pre-allocato:
# Pre-allocare il vettore per le prestazioni
n <- 10
fibonacci <- numeric(n)
fibonacci[1] <- 1
fibonacci[2] <- 1
for (i in 3:n) {
fibonacci[i] <- fibonacci[i - 1] + fibonacci[i - 2]
}
print(fibonacci)
# [1] 1 1 2 3 5 8 13 21 34 55
Alternative Vettoriali: sapply() e lapply()
In R, i cicli for sono generalmente piu lenti rispetto alle operazioni vettoriali. Le funzioni della famiglia apply offrono alternative piu efficienti e idiomatiche:
# Invece di un ciclo per calcolare i quadrati...
numeri <- 1:5
# Con il ciclo for
risultati_for <- numeric(5)
for (i in seq_along(numeri)) {
risultati_for[i] <- numeri[i]^2
}
print(risultati_for)
# [1] 1 4 9 16 25
# Con sapply() - più conciso ed efficiente
risultati_sapply <- sapply(numeri, function(x) x^2)
print(risultati_sapply)
# [1] 1 4 9 16 25
# Ancora meglio: operazione vettoriale diretta
risultati_vett <- numeri^2
print(risultati_vett)
# [1] 1 4 9 16 25
# lapply() restituisce una lista
nomi <- c("anna", "bruno", "carla")
nomi_maiuscoli <- lapply(nomi, toupper)
print(nomi_maiuscoli)
# [[1]]
# [1] "ANNA"
# [[2]]
# [1] "BRUNO"
# [[3]]
# [1] "CARLA"
# sapply() semplifica il risultato in un vettore quando possibile
nomi_maiuscoli_v <- sapply(nomi, toupper)
print(nomi_maiuscoli_v)
# anna bruno carla
# "ANNA" "BRUNO" "CARLA"
Quando possibile, preferire le operazioni vettoriali native di R o le funzioni sapply()/lapply() ai cicli for per ottenere codice piu leggibile e prestazioni migliori.
Conclusione
Il ciclo for in R è uno strumento versatile per iterare su vettori, liste e data frame. Le funzioni seq_along() e seq_len() garantiscono iterazioni sicure, mentre next e break offrono controllo sul flusso. Tuttavia, R è un linguaggio progettato per le operazioni vettoriali: quando possibile, è preferibile utilizzare sapply(), lapply() o le operazioni vettoriali dirette per scrivere codice piu efficiente e idiomatico.