Ecologia BIO231C_2018

Módulos practicos Ecología BIO231C-2018

>Curso: Ecología Bio231c
>Profesor: Pablo Marquet
>Jefe de ayudantes: Simón Castillo (spcastil@uc.cl)

Preámbulo

Contenidos


Trabajo práctico #1 Introducción a R y Principios de dinámicas poblacionales

1.1 Breve introducción a R y R-studio
1.1.1 Lenguaje básico I: operaciones, objetos, vectores, y listas
1.1.2 Lenguaje básico II: Loops y funciones básicas
1.2 Nociones de dinámicas poblacionales: modelos a tiempo continuo y a tiempo discreto
1.2.1 Modelo de crecimiento exponencial
1.2.2 Modelo de crecimiento logístico

Literatura de consulta
Van der Meer y Goldberg (2013) Population Ecology: First principles.
Neuhauser (2014) Calculus for biology and medicine.


Evaluaciones

Controles (n=2) 0.1NF
Takehome test 0.15NF

Módulo 1.1.1: Lenguaje básico I

Como una aproximación que facilite el entendimiento de algunos principios que describen las fluctuaciones demográficas, en estas sesiones indagaremos superficialmente en una herramienta que permite el modelamiento y la simulación de datos poblacionales (entre otros variados usos) que está siendo ampliamente utilizada dada su estructura de código abierto. Esta herramienta es R y la utilizaremos a través del IDE Rstudio.

En este módulo aprenderemos aspectos básicos y esenciales para comunicarnos con el PC a través de R/Rstudio. Algunas características generales de R nos permiten desde realizar cálculos sencillos hasta resolver ecuaciones diferenciales ordinarias (ODE). Comenzaremos con los usos más sencillos.

R como una calculadora

R puede ejecutar todas las operaciones matemáticas, por ejemplo: +, -, *, sqrt(), exp(), abs(), etc. Basta que le digamos a R de una forma clara que operación queremos realizar.
En la siguiente casilla escribe el código necesario para calcular la suma de las raíces cuadradas de 144 y 64
La función `sqrt()` entrega la raíz cuadrada de un número.
sqrt(144)+sqrt(64)

R utiliza lenguaje lógico

R puede realizar tests con operadores lógicos, tales como: <, >, ==, !=, etc. Tales operaciones nos permiten comparar de forma cualitativa dos o más elementos (numéricos o carácteres). Como resultado de la comparación ejecutada, obtenemos un elemento con resultados TRUE o FALSE de acuerdo a si la comparación elemento-a-elemento es verdadera o falsa, respectivamente.
Por ejemplo, a continuación evalúa si 5 es igual a 3:

 `==` evalúa si dos números, expresiones u objetos son iguales
5 == 3
R utiliza objetos
Para generar memoria en R, y no estar creado los mismos elemntos cada vez que los necesitamos, crearemos objetos, los cuales son paquetes de información, que alberga la sesión de R en su memoria. Podemos crear objetos simplemente utlizando el operador <- o bien =. Estos objetos pueden ser del tipo numérico, enteros, caracteres, complejos, etc.
# Creamos el objeto llamado 'a' cuyo valor es 435
a <- 435
#A partir de esto, cada vez que pongamos 'a' en el código (sin comillas)
#R entendera que nos referimos al número 435
a
a + 111
A continuación crea un objeto llamado b que sea el promedio de a y 300, e imprime (o llama) el valor del objeto b.
a <- 435
Para calcular promedios puedes utilizar la función `mean(c(...,...))`
a<- 435
b<-mean(c(a,300))
b

Un tipo de objeto que utilizaremos muy a menudo en R, son los vectores, que son objetos unidimensionales con un número definido (pero no necesariamente fijo en el tiempo) de elementos.
Para crear un vector numérico podemos utilizar las funciones c(), seq(), o simplemente el operador :.

vector_1  <- c(1,2,3,4,5,6,7) #En este sentido c() es decirle a R que haga una colección de objetos
vector_1b <- 1:7 #El operador : resulta en un vector de números enteros entre  min:max
vector_1c <- seq(1,7,1) #La funcion seq(min=, max=, by=)

#Llamamos a los vectores generados para visualizarlos
vector_1
vector_1b
vector_1c

Cada elemento del vector creado, independiente del tipo de vector, tiene una posición dentro del vector, que va desde la posición 1 al tamaño del vector (esto varía entre lenguajes de programación). Para todos los casos, en R podemos saber la longitud de un vector utilizando la función length(). Y para conocer el elemento que está en la posición ‘x’ del vector utilizamos nombrevector[x]. Notar que [] es para indicar la posición en una dimensión.
De esta forma para el vector creado anteriormente (vector_1):

vector_1  <- c(1,2,3,4,5,6,7) #En este sentido c() es decirle a R que haga una colección de objetos
length(vector_1)
vector_1[3] # Con esto buscamos el valor que está en la posición 3 en el objeto vector_1

Una nota al margen es necesaria, por cuanto para vectores con caracteres sólo podemos crearlos utilizando las funciones c(),paste(), o paste0(). Por lo tanto, la función seq(mínimo, máximo, delta) y el operador mínimo : máximo, sólo aplica a vectores numéricos.

vector_2<-c("Tyron", "Pickle Rick", "Elfo")
vector_2
#Para extraer el valor en la posición determinada ocupamos []
vector_2[3]
#Notar que este valor extraído lo podemos asignar a un nuevo objeto
iamelfo<-vector_2[3]
vector_2<-c("Tyron", "Pickle Rick", "Elfo")
#Notar que este valor extraído lo podemos asignar a un nuevo objeto
iamelfo<-vector_2[3]
 #Y luego llamar a ese objeto, y por ejemplo ejecutar una operación lógica
iamelfo == vector_2[1]
iamelfo == "elfo"

./?

a). ¿Cómo podrías combinar vectores? Importa si son de distinto tipo (e.g., numéricos con caracteres)?
b). ¿Puedes realizar operaciones entre vectores de distinto tipo o sobre un vector “mixto”?

Si necesitas crear un objeto con distintos vectores guardados de forma independiente puedes crear una lista, indexando en cada sección de esta lista, vectores distintos. Para indexar listas utilizaremos doble bracket [[y]] donde y corresponde a la subsección. Por ejemplo, creemos una lista un poco más compleja:

lista_1 <- list(seq(1:15), 3:6, "van Leeuwenhoek", "von Humboldt", c("Darwin", "Wallace"))

./?

b). ¿Cómo crearías una expresión a partir de esta lista_1, que extraiga el nombre de Darwin en función de su localización? Inténtalo acá:

lista_1 <- list(seq(1:15), 3:6, "van Leeuwenhoek", "von Humboldt", c("Darwin", "Wallace"))
Darwin es parte de una lista, pero también de un vector anidado en esa lista. Por lo que deberías indexar dos veces: `[[]]` para sección de la lista; y `[]` para posición en el vector.
lista_1 <- list(seq(1:15), 3:6, "van Leeuwenhoek", "von Humboldt", c("Darwin", "Wallace"))
lista_1[[5]][1]

***
Ejercicios

1. Operaciones matemáticas básicas
1.1 Calcula la suma de 133 + 515
1.2 Calcula el promedio de 578, 11, 100, 0.17

2. Vectores
2.1 Crea un vector de 1 a 100 con incrementos de 0.01. Guardalo como objeto ‘x’. Calcula la media, varianza y longitud de ‘x’.
2.2 Crea un vector con los siguientes nombres: Hegel, Marx, Engels, Butler, Spinoza. Guárdalo como un objeto llamado ‘y’.
2.3 Combina x e y en un solo objeto, ¿cuál es la longitud del nuevo objeto?
2.4 Crea un vector desde 144 a 12 con decrementos de 2. Cuál es el número en la posición 12 de este vector?
2.5 A partir del vector anterior, crea un nuevo vector con los valores en la posicion 10 y 20.

3. Listas
3.1 Crea una lista con los siguientes elementos: (1) tu nombre, (2) edad, (3) tus tres peliculas favoritas, (4) último libro que leíste y (5) tu carrera.
3.2 ¿Cómo podrías obtener el nombre de la segunda película?
3.3 ¿Cómo podrías modificar el último libro que leíste a parte de la indexación? (sin crear un nuevo objeto)

***

Módulo 1.1.2: Lenguaje básico II

For loops y funciones

Hasta el momento nos hemos remitido a tratar con variables estáticas (fijas, que no cambian) y además hemos utilizado funciones predefinidas en el rbase de R (conjunto de funciones predeterminadas). En esta sección realizaremos una introducción a el uso de for loops (cuando necesitamos automatizar un proceso ya sea en el tiempo, o bien para una lista o elementos de un vector) y a la escritura de funciones, ya que a veces podemos toparnos con que no existen las funciones que necesitamos y en lugar de perder horas buscando la función, quizás es más sencillo programarla uno mismo ;-).

  • For loops
Los for loops son instancias que nos permiten automatizar un proceso (y ahorrar mucho tiempo!!). Por ejemplo, si tenemos un vector al que a la mitad de los elementos queremos realizar cierta operación matemática, y otra operación a la mitad restante, en lugar de ir elemento por elemento basta con poner:
vector_3<-seq(1,10,1)
vector_3
for (i in 1:5){
    vector_3[i]<-vector_3[i]/10
}
for (i in 6:10){
    vector_3[i]<-vector_3[i]/100
}
vector_3

De esta forma, como podemos ver, la estructura general de un for loop es:
for (variable in* range*){
do something
}
Donde la variable creada es transitoria y utilizada sólo dentro del loop. en este caso esa variable puede indicar, entre otras cosas, la posición del elemento en el vector, o sólo un controlador temporal.
Otra forma es creando nuevos elementos, por así decirlo, independientes. Por ejemplo, en este caso i toma valores entre 1 y 100 con un incremento de 0.1. Es decir, vamos actualizando el valor del objeto i con cada paso temporal. El for loop lo que hace en este caso es que cada vez que genera un número, lo muestra (o imprime) utilizando para esto la función print():

for (i in seq(1,100,0.01)){
    print(i)
}
  • Funciones Hasta el momento sólo hemos utilizado funciones predefinidas en rbase, en esta breve introducción crearemos nuestras propias funciones (learn more). Cuando definimos la función, decidimos los argumentos que van ir dentro de esta función y que serán necesarios para que esta se ejecute. Por ejemplo, escribamos una función (llamada switch)para cambiar los valores de un vector binario dónde reemplazaremos los 0 por 1 y vice versa:
#Creamos el vector binario
binario_1<-c(1,1,1,1,1,0,0,0,0,0)

#Ahora definimos una funcion que llamaremos switch
switch<-function(x){
  for (n in 1:length(x)) {
    if(x[n]==0) x[n] <- x[n] + 1 # if es un condicional, que quiere decir que si se cumple la condicion entre paréntesis se realice lo que le sigue al paréntesis
    else x[n] <- x[n] - 1 # else indica que si no se cumple las condiciones anteriores se ejecute otra cosa
  } 
    return(x) #esto actualiza el vector binario_1
}
#Notar que esta funcion tiene sólo un argumento 'x', el cual corresponde al vector binario. 
#Ademas notar que en la redacción de la funcion estamos sumando o restando 1, 
#bien podriamos dejar solamente un 1 o un 0,respectivamente.

# Antes de ejecutar la función llamaremos al vector original
binario_1

#Ahora ejecutamos la función y vemos el output
switch(binario_1)

***
Ejercicio bonus

Imagina una población de \(N=\) 15 individuos, cada uno de los cuales puede estar sólo en un estado del espacio de estados posibles \(\omega_i \in \Omega = \{0,1\}\). Dado el vector initialState que define los estados iniciales en una población:

initialState<-c(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0)

Podemos definir el estado de un individuo \(i\) en un tiempo \((t)\) como \(\omega_i(t)\). Nota que en este caso en subíndice \(i\) indica la posición del individuo en el vector.
Misión: Crea una función llamada “spread” con dos argumentos: el vector inicial ‘x’ y un argumento asociado al número de generaciones a correr, la cual a cada paso temporal seleccione aleatoriamente uno de los 15 individuos en el vector inicial (excepto los de los extremos), y que cambie el estado de este individuo \(\omega_i(t) \rightarrow \omega_i(t+1)\) de acuerdo a las siguientes reglas:

  • Si \(\omega_i(t) = 0\) y \(\omega_{i-1}(t) = 1\) o \(\omega_{i+1}(t) = 1\), entonces \(\omega_i(t+1) = 1\)

  • Si \(\omega_i(t) = 0\) y \(\omega_{i-1}(t) = \omega_{i+1}(t) = 0\), entonces \(\omega_i(t+1) = 0\)

  • Si \(\omega_i(t) = 1\) y \(\omega_{i-1}(t) = \omega_{i+1}(t) = 0\), entonces \(\omega_i(t+1) = 1\)

  • Si \(\omega_i(t) = 1\) y \(\omega_{i-1}(t) = 1\) o \(\omega_{i+1}(t) = 1\), entonces \(\omega_i(t+1) = 0\)

Si lo logras, envía tu código dentro de las próximas 24hrs a spcastil@uc.cl y si está correcto obtendrás 0.5 puntos en el control!! (sólo para el primer estudiante que tenga el código correcto). May the force be w u ;-)

Simon P. Castillo - spcastil@uc.cl