00
:
00
:
00
:
00
Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

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.