中文 | Español | English | português | Turkish

source("single_populations_app_setup.R")

Consideremos la dinámica de población de una sola especie. Para simplificar comenzamos considerando una población cerrada, es decir, aquella en la que no hay inmigración ni emigración. La población solo crece cuando hay nacimientos y se reduce con las muertes. En una población que crece exponencialmente, no hay control sobre el crecimiento de la población; las tasas de natalidad y mortalidad permanecen constantes sin importar el tamaño de la población. Dado que $b$ es la tasa de natalidad per cápita y $d$ es la tasa de mortalidad per cápita, la dinámica de tal población se puede describir asi:

$$\frac{dN}{dT} = bN - dN = (b-d)N$$

Dado que $(b-d)$ es una constante que puede ser expresada como $r$, podemos escribir la ecuación de crecimiento exponencial de la siguiente manera:

$$\frac{dN}{dT} = rN$$

La trayectoria de una población que está experimentando crecimiento exponencial tiene una curva característica en forma de "J" cuando se grafica el tamaño de la población en función del tiempo, con el término $r$ controlando la forma de la J. Desplácese hacia abajo hasta la aplicación para explorar cómo el valor de $r$ influye en la trayectoria de la población.

Introduciendo algunos límites al crecimiento de la población

El modelo de crecimiento exponencial es simple y predice que, a largo plazo, cualquier población que experimente dicho crecimiento alcanzará un tamaño infinitamente grande. Dado que las poblaciones nunca crecen sin límites en la naturaleza, podemos mejorar este modelo.

Reexaminemos los supuestos del modelo de crecimiento exponencial, es decir, que hay una tasa de natalidad per cápita $b$ y una tasa de mortalidad per cápita $d$ que permanece constante en todo momento. Simplemente podemos relajar esta suposición examinando lo que sucede cuando la tasa de crecimiento neto ($rD$) disminuye linealmente a medida que una población alcanza una capacidad de carga ($K$) determinada por el medio ambiente. La dinámica de tal población se puede describir mediante la ecuación de crecimiento logístico:

$$\frac{dN}{dt} = rN \left(1-\frac{N}{K}\right)$$

Las poblaciones que experimentan un crecimiento logístico pueden crecer (es decir, tener una tasa de crecimiento de la población positiva) hasta que el tamaño de la población sea igual a la capacidad de carga ($N = K$). Cuando una población excede su capacidad de carga, la población tendrá una tasa de crecimiento negativa y se reducirá hasta la capacidad de carga.

Crecimiento logístico rezagado

En algunas circunstancias, la tasa de crecimiento de una población puede depender del tamaño de la población en algún momento del pasado. Por ejemplo, el rendimiento reproductivo de los individuos puede verse limitado por cuánto tuvieron que competir por los recursos cuando eran jóvenes. Podemos modelar tal escenario haciendo que la tasa de crecimiento de la población en el tiempo $t$ sea una función de algún tiempo $t-\tau$ en el pasado de la siguiente manera:

$$ \frac{dN}{dt} = rN_{t} \left(1-\frac{N_{t-\tau}}{K}\right)$$

Puede explorar las consecuencias del crecimiento logístico retardado eligiendo la opción "Dependencia de densidad rezagada" en la simulación de dependencia de la densidad.

Parameter table

pars_vars <- c("$r_i$", 
               "$K_i$", 
               "$N_i$",
               "$\\tau$")
descriptions <- c("Tasa de crecimiento intrínseco de la especie $i$",
                 "Capacidad de Carga de la especie $i$",
                 "Tamaño de la población de la especie $i$",
                 "Lapso para el crecimiento logístico retrasado (rezagado)")

param_df <- data.frame(pars_vars, descriptions)
kable(x = param_df, format = "html", 
      col.names = c("Parámetro/Variable", "Descripción")) %>%
  kable_styling(full_width = FALSE, 
                bootstrap_options = c("striped", "hover", "condensed"),
                position = "center")

Dinámica del Modelo

sidebarLayout(
  sidebarPanel(
    # User defined density dependent or independent growth ----
    radioButtons("densdep", "Crecimiento exponencial o logístico", 
                 choices = c(`Exponencial` = "indep", `Logístico` = "dep")),

    # User defined intrinsic growth rate r -----
    sliderInput("r_val", label = "Tasa de crecimiento intrínseco (r):",
                min = -0.25, max = 1, value = .25),

    # If Density Dependent growth requested, ask for K -----
    conditionalPanel(condition = "input.densdep == 'dep'",
                     sliderInput("K_val", label = "Capacidad de Carga (K)",
                                 min = 1, max = 10000, value = 500, step = 10)),
    # If Density Dependent growth requested, ask if time lag requested -----
    conditionalPanel(condition = "input.densdep == 'dep'",
                     radioButtons("densdepLag", label = "¿Crecimiento logístico rezagado?",
                                  choices = c(`No` = "nolag",`Si` = "lag"))),

    # If timelag requested in density-dependent growth, ask for tau -----
    conditionalPanel(condition = "input.densdepLag == 'lag'",
                     sliderInput("tau", label = "Lapso de tiempo (tau)",
                                 min = 0, max = 4, value = 1, step = .1)),

    # User defined initial population size  -----
    sliderInput("N1_val", label = "Tamaño inicial de la población",
                min = 1, max = 1000, value = 50, step = 10),
    hr(),

    # User can add a second species ----
    checkboxInput("secondsp", "¿Incluir segunda especie?", value = F), 

    # If second species requested, add the following... ----
    conditionalPanel(condition = "input.secondsp == true",
                     # User defined density dependent or independent growth for sp2 ----
                     radioButtons("densdep2", "Crecimiento exponencial o logístico", 
                                  choices = c(`Exponencial` = "indep", `Logístico` = "dep")),


                     # User defined intrinsic growth rate r2 -----
                     sliderInput("r_val2", label = "Tasa de crecimiento intrínseco de la Especie 2 (r2):",
                min = -0.25, max = 1, value = .25),

                     # If Density Dependent growth requested for sp2, ask for K2 -----
                     conditionalPanel(condition = "input.densdep2 == 'dep'",
                                      sliderInput("K_val2", label = "Capacidad de Carga de la Especie 2 (K2)",
                                                  min = 1, max = 10000, value = 500, step = 10),
                     ),
                     # If Density Dependent growth requested, ask if time lag requested -----
                     conditionalPanel(condition = "input.densdep2 == 'dep'",
                                      radioButtons("densdepLag2", label = "¿Crecimiento logístico rezagado?",
                                  choices = c(`No` = "nolag",`Si` = "lag"))),

                     # If timelag requested in density-dependent growth, ask for tau -----
                     conditionalPanel(condition = "input.densdepLag2 == 'lag'",
                                      sliderInput("tau2", label = "Lapso de tiempo (tau2)",
                                                  min = 0, max = 4, value = 1, step = .1)),
                     sliderInput("N2_val", label = "Tamaño inicial de la población de la Especie 2:",
                                 min = 1, max = 1000, value = 50, step = 10),
                         hr()),

    # User can select which plots to show ----
    checkboxGroupInput("plots_to_show", "Selecciona las figuras para mostrar",
                       c("N vs. Time" = "Nvtime",
                         "ln(N) vs. Time" = "lnNvtime",
                         "dN/dt vs. N" = "n1overn",
                         "dN/Ndt vs. N" = "n1novern"), selected = c("Nvtime", "lnNvtime")),
    hr(),

    # User defined length of simulation -----
    numericInput("max_time", label = "Duración de tiempo:",
                value = 100),

    ),



  # Panel of plots -----
  mainPanel(
    renderPlot({plots_to_print()}, width = 600,
               height = 600)
  )
)

# Get user defined parameters for sp 1  ------
params <- reactive({
  if(input$densdep == "indep") {
    c(r = input$r_val) 
  } else if(input$densdepLag == 'lag') {
    c(r = input$r_val, K = input$K_val, tau = input$tau) 
  } else {
    c(r = input$r_val, K = input$K_val) 
  }
})
init <- reactive({c(N1 = input$N1_val)})
time <- reactive({seq(from = 0, to = input$max_time, by=1)})

params2 <- reactive({
  if(input$densdep2 == "indep") {
    c(r = input$r_val2) 
  } else if(input$densdepLag2 == 'lag') {
    c(r = input$r_val2, K = input$K_val2, tau = input$tau2) 
  } else {
    c(r = input$r_val2, K = input$K_val2) 
  }
})
init2 <- reactive({c(N1 = input$N2_val)})

# Generate trajectories for sp 1 --------
pop_growth <- reactive({
  if(input$densdep == 'indep') {
    data.frame(ecoevoapps::run_exponential_model(time= time(), init = init(), params = params()))
  } else {
    data.frame(ecoevoapps::run_logistic_model(time= time(), init = init(), params = params()))
  }
})

# Generate trajectories for sp 2 --------
pop_growth2 <- reactive({
  if(input$secondsp) {
    if(input$densdep2 == 'indep') {
      data.frame(ecoevoapps::run_exponential_model(time= time(), init = init2(), params = params2()))
    } else {
      data.frame(ecoevoapps::run_logistic_model(time= time(), init = init2(), params = params2()))
    }
  }
}) 

pops_combined <- reactive({
  if(input$secondsp) {
    dplyr::bind_rows(pop_growth(), pop_growth2(),
                     .id = "which_pop")
  } else {
    pg <- pop_growth()
    pg$which_pop = "1"
    pg
  }
})
# Make plots -----------

# 0. Make caption  ------
plot_caption1 <- reactive({
  if(input$densdep == 'indep') {
  paste0("Parámetros de la Especie 1: r1 = ", input$r_val)
  } else if (input$densdepLag == "nolag") { 
    paste0("Parámetros de la Especie 1: r1 = ", input$r_val, ", K1 = ", input$K_val) 
    } else { 
    paste0("Parámetros de la Especie 1: r1 = ", input$r_val, ", K1 = ", input$K_val, ", Tau1 = ", input$tau) 
    }
})

plot_caption2 <- reactive({
  if(input$secondsp) {
    if(input$densdep2 == 'indep') {
      paste0("Parámetros de la Especie 2: r2 = ", input$r_val2)
    } else if (input$densdepLag2 == "nolag") { 
      paste0("Parámetros de la Especie 2: r2 = ", input$r_val2, ", K2 = ", input$K_val2) 
    } else { 
      paste0("Parámetros de la Especie 2: r2 = ", input$r_val2, ", K2 = ", input$K_val2, ", Tau2 = ", input$tau2) 
    }
  }
})

plot_caption <- reactive ({
  if(input$secondsp) {
    paste0(plot_caption1(), "\n", plot_caption2())
  } else {
    plot_caption1()
  }
})

# 1. Trajectory of N vs. time -----------
trajectory <- reactive({
  if("Nvtime" %in% input$plots_to_show) {
    ggplot(pops_combined()) + 
      geom_line(aes(x = time, y = N1, color = which_pop), linewidth = 2) +
      ecoevoapps::theme_apps() +
      scale_x_continuous(expand = c(0, 0, .1, 0)) +
      scale_y_continuous(expand = c(0, 0, .1, 0)) +
      annotate("text", x = 0, y = 0, label = "") +
      scale_color_brewer("Especie", palette = "Set1") +
      ylab("Tamaño de la población") +
      xlab("Tiempo")
    } 
})

# 2. Trjectory of ln(N) vs. time --------
trajectory_log <- reactive({
  if("lnNvtime" %in% input$plots_to_show) {
    ggplot(pops_combined()) + 
      geom_line(aes(x = time, y = log(N1), color = which_pop), linewidth = 2) +
      scale_color_brewer("Especie", palette = "Set1") +
      ecoevoapps::theme_apps() +
      scale_x_continuous(expand = c(0, 0, .1, 0)) +
      scale_y_continuous(expand = c(0, 0, .1, 0)) +
      annotate("text", x = 0, y = 0, label = "") +
      ylab("ln(Tamaño de la población)") +
      xlab("Tiempo")
    }
})

# 3. dN/dT vs. N -----------
n1_over_n <- reactive({
  if("n1overn" %in% input$plots_to_show) {

    dndt_out <- data.frame(dndt = dndt(params()), which_pop = "1")
    dndt_out$x <- 1:nrow(dndt_out)

    dndt_out_for_plot <-
      if(input$secondsp) {
        dn2dt_out <- data.frame(dndt = dndt(params2()), which_pop = "2")
        dn2dt_out$x <- 1:nrow(dn2dt_out)
        dplyr::bind_rows(dndt_out, dn2dt_out)
      } else {
        dndt_out
      }

    ggplot(dndt_out_for_plot) +
      geom_line(aes(x= x, y = dndt, color = which_pop), linewidth = 2) + 
      xlab("Tamaño de la población") + 
      ylab("Tasa de crecimiento de la popblación (dN/dt)") + 
      scale_color_brewer("Especie", palette = "Set1") +
      scale_x_continuous(expand = c(0, 0, .1, 0)) +
      scale_y_continuous(expand = c(0, 0, .1, 0)) +
      theme_apps() 
    }
})

# 4. dN/Ndt vs. N -----------
n1n_over_n <- reactive({
  if("n1novern" %in% input$plots_to_show) {

    dnNdt_out <- data.frame(dnNdt = dnNdt(params()), which_pop = "1")
    dnNdt_out$x <- 1:nrow(dnNdt_out)

    dnNdt_out_for_plot <-
      if(input$secondsp) {
        dnN2dt_out <- data.frame(dnNdt = dnNdt(params2()), which_pop = "2")
        dnN2dt_out$x <- 1:nrow(dnN2dt_out)
        dplyr::bind_rows(dnNdt_out, dnN2dt_out)
      } else {
        dnNdt_out
      }

    ggplot(dnNdt_out_for_plot) +
      geom_line(aes(x = x, y = dnNdt, color = which_pop), linewidth = 2) + 
      xlab("Tamaño de la población") + 
      ylab("Tasa per cápita de crecimiento de la popblación\n(dN/Ndt)") + 
      scale_color_brewer("Especie", palette = "Set1") +
      scale_x_continuous(expand = c(0, 0, .1, 0)) +
      # limits = c(0, min(max(pop_growth()$N1)), max(pop_growth2()$N1)
      scale_y_continuous(limits = c(-0.26, 1),                           expand = c(0, 0, .1, 0)) +
      theme_apps() 
    }
})

# Make a list of plots and print out plots based on which ones were requested ----
plot_list <- reactive({
  list(trajectory(), trajectory_log(),
       n1_over_n(), n1n_over_n()) %>% 
    discard(is.null)
  })

plots_to_print <- reactive({
  wrap_plots(plot_list(), ncol = 2) + 
    labs(caption = plot_caption()) + 
    plot_layout(guides = "collect") & theme(legend.position = 'bottom')
})

Lectura adicional

"How populations grow: the Exponential and the logistic", John Vandermeer, Nature Education Knowledge.

"Exponential & logistic growth" at Khan Academy.


suppressWarnings(ecoevoapps::print_app_footer(language = "es"))


gauravsk/ecoevoapps documentation built on July 9, 2024, 9:37 p.m.