Ciclo For in R con esempi di lista e matrice

⚡ Riepilogo intelligente

In R, il ciclo for esegue un blocco di codice una volta per ogni elemento di una sequenza, che si tratti di un vettore, una lista o una matrice. Questa guida illustra ciascuno di questi casi e mostra quando l'utilizzo di un codice vettorializzato rappresenta la scelta migliore.

  • 🔁 Sintassi di base: per (i in vettore) { espressione } assegna ciascun elemento a i a turno ed esegue il corpo.
  • 📋 Qualsiasi oggetto: La stessa sintassi si applica a un vettore, a una lista, a un insieme di colonne di un data frame o alle righe di una matrice.
  • 🧮 Cicli annidati: Una matrice necessita di due cicli: uno esterno per le righe e uno interno per le colonne.
  • 🛑 Controllo del flusso: break interrompe completamente il ciclo e next salta solo l'elemento corrente.
  • ⚡ Prima la vettorizzazione: Le operazioni vettorializzate integrate e la famiglia apply sono più veloci e concise rispetto a un ciclo esplicito.
  • ⚠️ Sequenze sicure: Utilizzare seq_along(x) anziché 1:length(x), che si comporta in modo anomalo quando l'oggetto è vuoto.

Ciclo for in R List Matrix

A per loop Ripete un blocco di codice una volta per ogni elemento di una sequenza. Tale sequenza può essere un vettore, una lista, un data frame, una matrice o qualsiasi altro oggetto su cui R può iterare. R distingue tra maiuscole e minuscole, quindi la parola chiave è sempre in minuscolo. pere le parentesi graffe sono necessarie ogni volta che il corpo del testo si estende su più di una riga.

Sintassi del ciclo for in R

for (i in vector) {
    Exp
}

Qui,

R eseguirà il loop su tutte le variabili in vector ed eseguirà il calcolo scritto all'interno di exp.

Per il ciclo in R
Per il ciclo in R

Vediamo alcuni esempi.

Ciclo For in R Esempio 1: Iteriamo su tutti gli elementi di un vettore e stampiamo il valore corrente.

# Create fruit vector
fruit <- c('Apple', 'Orange', 'Passion fruit', 'Banana')
# Create the for statement
for ( i in fruit){ 
 print(i)
}

Produzione:

## [1] "Apple"
## [1] "Orange"
## [1] "Passion fruit"
## [1] "Banana"

Ciclo For in R Esempio 2: eleva al quadrato ogni numero intero da 1 a 4 e memorizza i risultati in una lista.

# Create an empty list
list <- c()
# Create a for statement to populate the list
for (i in seq(1, 4, by=1)) {
  list[[i]] <- i*i
}
print(list)

Produzione:

## [1]   1  4 9 16

I cicli for sono utili nel lavoro di apprendimento automatico. La regolazione di un parametro di regolarizzazione significa testare molti valori candidati e mantenerliping quella che minimizza la funzione di perdita, e un ciclo for è il modo più semplice per esplorare quell'intervallo.

Come utilizzare break e next in un ciclo for

Due parole chiave interrompono la normale sequenza di un ciclo for.

  • rompere esce immediatamente dal ciclo e salta ogni elemento rimanente.
  • GENERAZIONE abbandona solo l'elemento corrente e passa a quello successivo.
fruit <- c('Apple', 'Orange', 'Passion fruit', 'Banana')

# break: stop at the first match
for (i in fruit) {
    if (i == 'Passion fruit') {
        print('Found it, stopping here')
        break
    }
    print(i)
}

# next: skip one element and carry on
for (i in fruit) {
    if (i == 'Orange') next
    print(i)
}

Nei cicli annidati, break e next agiscono solo sul ciclo più interno che li contiene. Per lasciare entrambi i cicli in sospeso nell'esempio della matrice, imposta una variabile flag e controllala anche nel ciclo esterno.

Utilizzare seq_along() per gli indici. Scrivere for (i in 1:length(x)) sembra innocuo ma fallisce su un oggetto vuoto, perché 1:0 produce la sequenza 1, 0 e il ciclo viene eseguito due volte. seq_along(x) restituisce invece una sequenza vuota, quindi il ciclo viene saltato correttamente:

for (i in seq_along(fruit)) {
    cat(i, fruit[i], '\n')
}

Ciclo For su una lista

gabinettoping su una lista funziona esattamente come il bagnoping su un vettore, con la differenza che ogni elemento può contenere un tipo diverso:

# Create a list with three vectors
fruit <- list(Basket = c('Apple', 'Orange', 'Passion fruit', 'Banana'), 
Money = c(10, 12, 15), purchase = FALSE)
for (p  in fruit) 
{ 
	print(p)
}

Produzione:

## [1] "Apple" "Orange" "Passion fruit" "Banana"       
## [1] 10 12 15
## [1] FALSE

Ciclo for su una matrice

Una matrice ha due dimensioni, righe e colonne, quindi per iterare su ogni cella sono necessari due cicli for annidati: uno esterno per le righe e uno interno per le colonne.

# Create a matrix
mat <- matrix(data = seq(10, 20, by=1), nrow = 6, ncol =2)
# Create the loop with r and c to iterate over the matrix
for (r in 1:nrow(mat))   
    for (c in 1:ncol(mat))  
         print(paste("Row", r, "and column",c, "have values of", mat[r,c]))  

Produzione:

## [1] "Row 1 and column 1 have values of 10"
## [1] "Row 1 and column 2 have values of 16"
## [1] "Row 2 and column 1 have values of 11"
## [1] "Row 2 and column 2 have values of 17"
## [1] "Row 3 and column 1 have values of 12"
## [1] "Row 3 and column 2 have values of 18"
## [1] "Row 4 and column 1 have values of 13"
## [1] "Row 4 and column 2 have values of 19"
## [1] "Row 5 and column 1 have values of 14"
## [1] "Row 5 and column 2 have values of 20"
## [1] "Row 6 and column 1 have values of 15"
## [1] "Row 6 and column 2 have values of 10" 

Ciclo for su un DataFrame in R

Un data frame è un elenco di colonne, quindi un semplice ciclo for scorre le sue colonne anziché le sue righe. Questo è generalmente ciò che si desidera:

df <- data.frame(a = 1:5, b = 6:10, c = 11:15)

# Loop over the columns
for (col in names(df)) {
    cat(col, 'has mean', mean(df[[col]]), '\n')
}

Nota la doppia parentesi. df[[col]] extracts restituisce la colonna come un vettore, mentre df[col] restituisce un data frame a una colonna che mean() non è in grado di gestire.

gabinettoping su più righe. L'iterazione riga per riga è possibile ma lenta, perché R copia la riga a ogni passaggio:

for (r in seq_len(nrow(df))) {
    cat('Row', r, 'sums to', sum(df[r, ]), '\n')
}

Per qualsiasi cosa che superi qualche migliaio di righe, preferisci rowSums(df), apply(df, 1, sum) o un dplyr raggruppare per() e riassumere() pipeline, tutte le quali svolgono lo stesso lavoro senza la copia.

Cicli for vs vettorizzazione in R

R è un linguaggio vettorializzato: la maggior parte dei suoi operatori e funzioni agiscono già simultaneamente su interi vettori, nel codice C compilato. Un ciclo esplicito che ripete un'operazione vettorializzata elemento per elemento è sia più lungo che più lento.

# Loop version
squares <- c()
for (i in 1:4) {
    squares[i] <- i * i
}

# Vectorized version, same result
squares <- (1:4)^2
Task Ciclo continuo Equivalente vettoriale
Aritmetica elemento per elemento per ogni elemento x * 2, x + y, x^2
Applica una funzione per colonna per oltre nomi(df) applica(df, media)
Applica una funzione per riga per oltre seq_len(nrow(df)) applica(df, 1, somma)
Crea un elenco di risultati per con lista[[i]] <- … lapply(v, f)
Ricodifica condizionale per con se e altrimenti ifelse(cond, a, b)

Quando un ciclo è ancora la risposta giusta. Mantieni il ciclo for quando ogni iterazione dipende dal risultato precedente, quando chiami un servizio esterno o scrivi file, oppure quando la chiarezza è più importante della velocità su un oggetto di piccole dimensioni.

Se è necessario utilizzare un ciclo, preallocate la memoria. Espandere un oggetto all'interno di un ciclo costringe R a copiarlo a ogni passaggio. Crealo prima a dimensioni reali:

# Slow: the vector is reallocated on every pass
out <- c()
for (i in 1:1000) out[i] <- i^2

# Fast: allocated once
out <- numeric(1000)
for (i in 1:1000) out[i] <- i^2

Ciclo For in R: Guida rapida

Di seguito è riportato l'elenco di tutte le strutture utilizzate in questo tutorial:

Obiettivo Code
Ciclo su un vettore
for (i in v) { print(i) }
Iterare sugli indici in modo sicuro
for (i in seq_along(v)) { print(v[i]) }
Passa il mouse su un elenco
for (p in my_list) { print(p) }
Scorrere le colonne del dataframe
for (col in names(df)) { print(mean(df[[col]])) }
Ciclo su una matrice
for (r in 1:nrow(m)) for (c in 1:ncol(m)) print(m[r, c])
Esci dal ciclo in anticipo
if (condition) break
Salta un'iterazione
if (condition) next
Preassegnare l'output
out <- numeric(n)

DOMANDE FREQUENTI

Quando x è vuoto, 1:length(x) restituisce la sequenza 1, 0 e il ciclo viene eseguito due volte su elementi inesistenti. seq_along(x) restituisce una sequenza vuota, quindi il ciclo viene saltato correttamente.

Il ciclo in sé non è il problema. Il problema è la crescita di un oggetto al suo interno, perché R copia l'intero oggetto a ogni iterazione. Preallocando il risultato o utilizzando una funzione vettorizzata, il problema si risolve in gran parte.

Colonne. Un data frame è un elenco di colonne, quindi ogni iterazione restituisce un'intera colonna. Utilizza esplicitamente seq_len(nrow(df)) se devi invece scorrere le righe.

I cicli for guidano le analisi degli iperparametri, le iterazioni di convalida incrociata e le epoche di addestramento. Ognuna di queste ha un numero di iterazioni noto, che è esattamente lo scopo per cui è stato progettato il costrutto for.

Sì. Gli assistenti IA possono convertire la maggior parte dei cicli elemento per elemento in equivalenti vettoriali o basati su apply-family. Confronta l'output di entrambe le versioni con identical() prima di sostituire l'originale.

Riassumi questo post con: