for (i in 1:10) {
print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
¿Te encuentras cortando y pegando código de R con frecuencia?
Esto generalmente creará problemas para ti más adelante. Uno de los principios de una buena codificación es tratar de reducir al mínimo la repetición. Hay dos enfoques para organizar tu código y ahorrarte trabajo. El primero es usar funciones y el segundo, cubierto aquí, es usar bucles.
A menudo, queremos realizar tareas repetitivas en las ciencias ambientales. Por ejemplo, es posible que deseemos recorrer una lista de archivos y hacer lo mismo una y otra vez. Hay muchos paquetes en R con funciones que harán todo el trabajo duro por ti (por ejemplo, echa un vistazo a dplyr, tidyr y reshape2 cubiertos aquí). El enfoque de dplyr funciona bien si tus datos son “ordenados” y están en un marco de datos. Si tus datos están en muchos archivos diferentes, entonces un bucle puede ser una solución más rápida.
La sintaxis de los bucles es relativamente simple: los componentes esenciales son for(){}
donde la parte for()
indica cuántas veces se realizan las operaciones dentro de {}
.
Considera el siguiente bucle. La primera vez que recorremos el bucle, el valor de i será igual a 1 y este valor se mostrará con la función print
. Luego se repetirá con i = 2, hasta i = 10, realizando la tarea que se encuentra dentro de {}
cada vez.
for (i in 1:10) {
print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
Podemos cambiar el rango de números (1:10) a cualquier cosa que deseemos, no tienen que ser una secuencia de enteros o incluso números. También puedes cambiar i a cualquier valor que desees.
<- c(3.2, 890, 0.0001, 400)
nums
for (bat in nums) {
print(bat)
}
[1] 3.2
[1] 890
[1] 1e-04
[1] 400
<- c("a", "o", "u", "z")
chars
for (bat in chars) {
print(bat)
}
[1] "a"
[1] "o"
[1] "u"
[1] "z"
De mayor interés para nosotros es cambiar lo que está dentro de {}
o la operación que estamos realizando en nuestros datos. Podemos insertar cualquier cosa que deseemos aquí. Aquí hay un bucle que imprimirá el cuadrado y la raíz cuadrada de los números del 1 al 10.
for (i in 1:10) {
print(i^2)
print(sqrt(i))
}
A menudo, querremos mantener los resultados que obtenemos de nuestro bucle. La primera opción es crear un vector o marco de datos vacío y agregar los resultados a él. Esto tarda más en ejecutarse, pero no importa realmente con bucles simples, aunque puede aumentar los tiempos de espera para estructuras de bucle más largas y complicadas.
Aquí hay un código que almacenará el cuadrado de los números del 1 al 10 en un nuevo vector llamado x.
<- vector() # makes a blank vector
x
for (i in 1:10) {
<- i^2 # performs an operation
y <- append(x, y) # overwrites 'x' with y appended to it
x }
Aquí hay un código que almacenará tanto el cuadrado como la raíz cuadrada de los números del 1 al 10 en dos columnas de un nuevo marco de datos llamado x2.
<- data.frame(col1 = vector(), col2 = vector()) # makes a blank data frame with two columns
x2
for (i in 1:10) {
<- i^2 # performs first operation
col1 <- sqrt(i) # performs second operation
col2 <- rbind(x2, cbind(col1, col2)) # overwrites 'x2' values including the new row
x2 }
La segunda opción es crear un vector o marco de datos vacío de dimensiones conocidas y luego colocar los resultados directamente en él. Por ejemplo, si tuviéramos un bucle con 10 elementos, podríamos almacenar los resultados de cada operación en un vector con una longitud 10.
<- vector(length = 10) # makes a blank vector with a length of 10
x
for (i in 1:10) {
<- i^2
y <- y # places the output in position i in the vector x
x[i] }
Alternativamente, guarda los resultados de múltiples operaciones en un nuevo data frame.
<- data.frame(col1 = vector(length = 10), col2 = vector(length = 10)) # makes a blank data frame with two columns and 10 rows
x2
for (i in 1:10) {
<- i^2 # performs first operation
col1 <- sqrt(i) # performs second operation
col2 1] <- col1 # places the first result into row i, column 1
x2[i, 2] <- col2 # places the second result into row i, column 2
x2[i, }
Ahora podemos utilizar tus nuevas habilidades de bucle en un contexto ecológico. Al igual que en el tutorial de Subconjuntos de datos, utilizaremos un conjunto de datos donde se muestrearon murciélagos en un bosque en regeneración en el sureste de Australia, que ha sido adelgazado para reducir la densidad de árboles.
<- read.csv(file = "Bats_data.csv", header = T, stringsAsFactors = F)
Bats str(Bats)
'data.frame': 173 obs. of 10 variables:
$ Site : chr "CC02A1" "CC02A1" "CC02A1" "CC02A2" ...
$ Activity : int 299 276 530 356 571 631 144 124 220 468 ...
$ Foraging : int 0 6 14 5 3 17 3 0 7 8 ...
$ Date : chr "9/01/2013" "8/01/2013" "7/01/2013" "8/01/2013" ...
$ Treatment.thinned : chr "medium-term" "medium-term" "medium-term" "medium-term" ...
$ Area.thinned : num 0 0 0 0 0 0 0 0 0 0 ...
$ Time.since.thinned : int 7 7 7 7 7 7 7 7 7 7 ...
$ Exclusion.thinned : num 25.1 25.1 25.1 25.1 25.1 ...
$ Distance.murray.water: num 190 190 190 216 216 ...
$ Distance.creek.water : num 444 444 444 885 885 ...
Al analizar la estructura de estos datos, tenemos dos variables de respuesta: actividad (número de llamadas de murciélagos registradas en una noche) y forrajeo (número de llamadas de alimentación de murciélagos registradas en una noche). Estos datos se recolectaron durante un total de 173 noches de estudio y en 47 sitios diferentes. Hay ocho posibles variables predictoras en el marco de datos, una de las cuales es un factor (Tratamiento.adelgazado), y siete de las cuales son variables continuas (Área.adelgazada, Tiempo.desde.adelgazamiento, Exclusión.adelgazada, Distancia.agua.murray, Distancia.agua.arroyo, Promedio.T, Promedio.H).
Digamos que estamos explorando nuestros datos y nos gustaría saber qué tan bien se correlaciona la actividad de los murciélagos con nuestras covariables continuas. Nos gustaría calcular el coeficiente de correlación de Pearson para la actividad y cada una de las covariables por separado. El coeficiente de correlación de Pearson, calculado con la función cor
, varía de -1 (correlación negativa perfecta) a 1 (correlación positiva perfecta), siendo 0 ninguna correlación. Almacenaremos todas nuestras correlaciones en un nuevo data frame llamado Correlations.
Primero, usa select
de dplyr para hacer una subconjunto de los datos con la variable de respuesta (actividad) y las 5 variables predictoras.
library(dplyr)
<- select(Bats, Activity, Area.thinned:Distance.creek.water) Bats_subset
A continuación, crea un data frame vacío con dos columnas (el nombre de la variable y la correlación) y el número de filas necesario para almacenar todas las correlaciones.
<- ncol(Bats_subset) - 1 # the number of rows needed in our output dataframe
rows
<- data.frame(
Correlations variable = character(length = rows),
correlation = numeric(length = rows),
stringsAsFactors = F
)
Finalmente, podemos utilizar un bucle para calcular cada una de las correlaciones y almacenar la salida en nuestro nuevo data frame.
for (i in 1:rows) {
<- colnames(Bats_subset[i + 1]) # retrieves the name of predictor variable
temp1 <- cor(Bats_subset[, 1], Bats_subset[, i + 1], method = "pearson")
temp2 # calculates the correlation between activity and predictor variable
1] <- temp1 # places the variable name into row i, column 1
Correlations[i, 2] <- temp2 # places the correlation into row i, column 2
Correlations[i, }
variable correlation
1 Area.thinned -0.40890389
2 Time.since.thinned -0.02135752
3 Exclusion.thinned 0.17562438
4 Distance.murray.water -0.18071570
5 Distance.creek.water -0.09130258
Ahora podemos ver de un vistazo que la actividad está más fuertemente correlacionada (negativamente) con el área adelgazada y que no está correlacionada en absoluto con el tiempo desde el adelgazamiento o la temperatura media. Es posible que luego deseemos investigar más a fondo algunas de estas relaciones con modelos y pruebas estadísticas apropiadas.
Tutorial de DataCamp sobre bucles
Puedes encontrar más ejemplos buenos de bucles, listas y declaraciones if/else en el sitio GitHub del grupo de usuarios de R de BEES Bucles y listas por Mitch.
Autor: Rachel V. Blakey
Año: 2016
Última actualización: Nov. 2023