For Loop en R con ejemplos de lista y matriz

⚡ Resumen inteligente

En R, el bucle `for` ejecuta un bloque de código una vez por cada elemento de una secuencia, ya sea un vector, una lista o una matriz. Este tutorial recorre cada una de ellas y muestra cuándo el código vectorizado es la mejor opción.

  • 🔁 Sintaxis básica: para (i en vector) { expresión } asigna cada elemento a i por turno y ejecuta el cuerpo.
  • 📋 Cualquier objeto: La misma sintaxis se aplica a un vector, una lista, un conjunto de columnas de un marco de datos o las filas de una matriz.
  • 🧮 Bucles anidados: Una matriz necesita dos bucles: uno exterior para las filas y otro interior para las columnas.
  • 🛑 Control de flujo: break sale del bucle por completo y next solo omite el elemento actual.
  • Primero la vectorización: Las operaciones vectorizadas integradas y la familia de funciones apply son más rápidas y concisas que un bucle explícito.
  • ⚠️ Secuencias seguras: Utilice seq_along(x) en lugar de 1:length(x), que se comporta de forma incorrecta cuando el objeto está vacío.

Bucle for en R Lista Matriz

A en bucle Repite un bloque de código una vez por cada elemento de una secuencia. Dicha secuencia puede ser un vector, una lista, un marco de datos, una matriz o cualquier otro objeto sobre el que R pueda iterar. R distingue entre mayúsculas y minúsculas, por lo que la palabra clave siempre se escribe en minúsculas. por lay las llaves son necesarias siempre que el texto abarque más de una línea.

Sintaxis del bucle for en R

for (i in vector) {
    Exp
}

Aquí,

R recorrerá todas las variables en el vector y realizará el cálculo escrito dentro de la exp.

Para bucle en R
Para bucle en R

Veamos algunos ejemplos.

Bucle For en R Ejemplo 1: Iteramos sobre todos los elementos de un vector e imprimimos el valor actual.

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

Salida:

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

Bucle For en R Ejemplo 2: eleva al cuadrado cada número entero del 1 al 4 y almacena los resultados en 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)

Salida:

## [1]   1  4 9 16

Los bucles for son útiles en el trabajo de aprendizaje automático. Ajustar un parámetro de regularización significa probar muchos valores candidatos y mantenerping la que minimiza la función de pérdida, y un bucle for es la forma más sencilla de recorrer ese rango.

Cómo usar break y next en un bucle for

Dos palabras clave interrumpen la secuencia normal de un bucle for.

  • romper Sale del bucle inmediatamente y omite todos los elementos restantes.
  • Next Abandona únicamente el elemento actual y pasa al siguiente.
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)
}

En bucles anidados, `break` y `next` solo actúan sobre el bucle más interno que los contiene. Para mantener ambos bucles en el ejemplo de la matriz, establezca una variable de bandera y compruébela también en el bucle externo.

Utilice seq_along() para los índices. Escribir `for (i in 1:length(x))` parece inofensivo, pero falla con un objeto vacío, porque `1:0` produce la secuencia `1, 0` y el bucle se ejecuta dos veces. `seq_along(x)` devuelve una secuencia vacía, por lo que el bucle se omite correctamente:

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

Bucle for sobre una lista

lavaboping sobre una lista funciona exactamente como looping sobre un vector, excepto que cada elemento puede contener un tipo diferente:

# 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)
}

Salida:

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

Bucle for sobre una matriz

Una matriz tiene dos dimensiones, filas y columnas, por lo que iterar sobre cada celda requiere dos bucles for anidados: uno externo para las filas y otro interno para las columnas.

# 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]))  

Salida:

## [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" 

Bucle for sobre un marco de datos en R

Un marco de datos es una lista de columnas, por lo que un bucle for simple recorre sus columnas en lugar de sus filas. Eso es generalmente lo que se desea:

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')
}

Nótese el doble corchete. df[[col]] extracts la columna como un vector, mientras que df[col] devuelve un marco de datos de una sola columna que mean() no puede manejar.

lavaboping sobre filas. La iteración fila por fila es posible pero lenta, porque R copia la fila en cada pasada:

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

Para cualquier cosa que supere unos pocos miles de filas, prefiera rowSums(df), apply(df, 1, sum) o un dplyr. agrupar_por() y resumir() canalización, todas las cuales realizan el mismo trabajo sin copiar.

Bucles for frente a vectorización en R

R es un lenguaje vectorizado: la mayoría de sus operadores y funciones ya actúan sobre vectores completos a la vez, en código C compilado. Un bucle explícito que repite una operación vectorizada elemento por elemento es más largo y lento.

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

# Vectorized version, same result
squares <- (1:4)^2
Task Loop Equivalente vectorizado
Aritmética por elementos para cada elemento x * 2, x + y, x^2
Aplicar una función por columna para sobre nombres(df) aplicar(df, media)
Aplicar una función por fila para seq_len(nrow(df)) aplicar(df, 1, suma)
Crea una lista de resultados para con lista[[i]] <- … lapply(v, f)
Recodificación condicional porque con si y de lo contrario ifelse(cond, a, b)

Cuando un bucle sigue siendo la respuesta correcta. Mantén el bucle for cuando cada iteración dependa del resultado anterior, cuando estés llamando a un servicio externo o escribiendo archivos, o cuando la claridad importe más que la velocidad en un objeto pequeño.

Si necesita usar un bucle, asigne memoria previamente. Si se crea un objeto dentro de un bucle, R se verá obligado a copiarlo en cada iteración. Primero, créelo con su tamaño completo:

# 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

Bucle for en R: Guía rápida

A continuación se enumeran todos los elementos utilizados en este tutorial:

Objetivo Code
Recorrer un vector
for (i in v) { print(i) }
Recorrer los índices de forma segura
for (i in seq_along(v)) { print(v[i]) }
Recorrer una lista
for (p in my_list) { print(p) }
Recorrer las columnas del marco de datos
for (col in names(df)) { print(mean(df[[col]])) }
Recorrer una matriz
for (r in 1:nrow(m)) for (c in 1:ncol(m)) print(m[r, c])
Salga del bucle pronto
if (condition) break
Saltar una iteración
if (condition) next
Preasignar la salida
out <- numeric(n)

Preguntas Frecuentes

Cuando x está vacío, 1:length(x) devuelve la secuencia 1, 0 y el bucle se ejecuta dos veces en elementos inexistentes. seq_along(x) devuelve una secuencia vacía, por lo que el bucle se omite correctamente.

El bucle en sí no es el problema. El problema radica en el crecimiento del objeto dentro del bucle, ya que R copia el objeto completo en cada iteración. Si se preasigna el resultado o se utiliza una función vectorizada, la brecha prácticamente desaparece.

Columnas. Un marco de datos es una lista de columnas, por lo que cada iteración devuelve una columna completa. Si necesita recorrer las filas, utilice explícitamente seq_len(nrow(df)).

Los bucles for controlan el barrido de hiperparámetros, las iteraciones de validación cruzada y las épocas de entrenamiento. Cada una de estas iteraciones tiene un número conocido de repeticiones, que es precisamente para lo que está diseñado el bucle for.

Sí. Los asistentes de IA pueden convertir la mayoría de los bucles elemento a elemento en equivalentes vectorizados o de tipo apply-family. Compare el resultado de ambas versiones con identical() antes de reemplazar la original.

Resumir este post con: