Looking for r Answers? Try Ask4KnowledgeBase
Looking for r Keywords? Try Ask4Keywords

R LanguageEstructuras de flujo de control


Observaciones

Los bucles son un método de control de flujo para repetir una tarea o un conjunto de tareas en un dominio. La estructura central de un bucle for es

for ( [index] in [domain]){
  [body]
}

Dónde

  1. [index] es un nombre que toma exactamente un valor de [domain] sobre cada iteración del bucle.
  2. [domain] es un vector de valores sobre los cuales iterar.
  3. [body] es el conjunto de instrucciones para aplicar en cada iteración.

Como ejemplo trivial, considere el uso de un bucle for para obtener la suma acumulativa de un vector de valores.

x <- 1:4
cumulative_sum <- 0
for (i in x){
  cumulative_sum <- cumulative_sum + x[i]
}
cumulative_sum

Optimizando la estructura de los bucles for

Para los bucles puede ser útil para conceptualizar y ejecutar tareas para repetir. Si no es cuidadosamente construido, sin embargo, pueden ser muy lento para ejecutar en comparación con el preferido usado del apply familia de funciones. No obstante, hay un puñado de elementos que puede incluir en su construcción de bucle for para optimizar el bucle. En muchos casos, una buena construcción del bucle for dará una eficiencia computacional muy cercana a la de una función de aplicación.

Un 'construido adecuadamente' para un bucle se basa en la estructura central e incluye una declaración que declara el objeto que capturará cada iteración del bucle. Este objeto debe tener una clase y una longitud declarada.

[output] <- [vector_of_length]
for ([index] in [length_safe_domain]){
  [output][index] <- [body]
}

Para ilustrar, escribamos un bucle para cuadrar cada valor en un vector numérico (este es un ejemplo trivial solo para ilustración. La forma 'correcta' de completar esta tarea sería x_squared <- x^2 ).

x <- 1:100
x_squared <- vector("numeric", length = length(x))
for (i in seq_along(x)){
  x_squared[i] <- x[i]^2
}

Nuevamente, note que primero x_squared un receptáculo para la salida x_squared , y le dimos la clase "numérica" ​​con la misma longitud que x . Además, seq_along un "dominio seguro de longitud" utilizando la función seq_along . seq_along genera un vector de índices para un objeto que es adecuado para usar en bucles. Si bien parece intuitivo de usar for (i in 1:length(x)) , si x tiene una longitud de 0, el bucle intentará iterar sobre el dominio de 1:0 , lo que generará un error (el índice 0 no está definido en R ).

Objetos receptáculo y dominios seguros de longitud se manejan internamente por el apply familia de funciones y los usuarios se les anima a adoptar el apply el enfoque en el lugar de los bucles tanto como sea posible. Sin embargo, si se construye correctamente, un bucle for ocasionalmente puede proporcionar una mayor claridad de código con una pérdida mínima de eficiencia.

Vectorización para bucles

A menudo, los bucles pueden ser una herramienta útil para conceptualizar las tareas que deben completarse dentro de cada iteración. Cuando el bucle está completamente desarrollado y conceptualizado, puede haber ventajas en convertir el bucle en una función.

En este ejemplo, desarrollaremos un bucle for para calcular la media de cada columna en el conjunto de datos mtcars (de nuevo, un ejemplo trivial como podría lograrse a través de la función colMeans ).

column_mean_loop <- vector("numeric", length(mtcars))
for (k in seq_along(mtcars)){
  column_mean_loop[k] <- mean(mtcars[[k]])
}

El bucle for se puede convertir en una función de aplicación reescribiendo el cuerpo del bucle como una función.

col_mean_fn <- function(x) mean(x)
column_mean_apply <- vapply(mtcars, col_mean_fn, numeric(1))

Y para comparar los resultados:

identical(column_mean_loop, 
          unname(column_mean_apply)) #* vapply added names to the elements
                                     #* remove them for comparison

Las ventajas de la forma vectorizada es que pudimos eliminar algunas líneas de código. La función de aplicación se encarga de la mecánica de determinar la longitud y el tipo del objeto de salida y la iteración de un dominio seguro de longitud. Además, la función de aplicación es un poco más rápida que el bucle. La diferencia de velocidad es a menudo despreciable en términos humanos según el número de iteraciones y la complejidad del cuerpo.

Estructuras de flujo de control Ejemplos relacionados