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

source("single_populations_app_setup.R")

Aqui vamos considerar a dinâmica populacional de uma única espécie. Para tornar as coisas um pouco mais simples, vamos por ora considerar essa uma população "fechada", isto é, uma população que não está sujeita a imigração ou emigração. Essa população, portanto, apenas pode crescer com o aumento da natalidade e/ou redução da mortalidade. Uma população com acesso ilimitado a recursos crescerá exponencialmente e suas taxas de natalidade e mortalidade permanecerão constantes ao longo do tempo ($T$), independentemente do tamanho populacional ($N$). Se $b$ e $d$ forem, respectivamente, as taxas de natalidade e mortalidade per capita, então a taxa de crescimento populacional pode ser descrita como:

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

Dado que $(b-d)$ é uma constante ($r$), chamada de taxa de crescimento intrínseco, podemos reescrever a equação acima da seguinte forma:

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

A trajetória de uma população em crescimento exponencial tem um formato de "J" num gráfico de tamanho populacional ($N$) em função do tempo ($T$).

Impondo limites ao crescimento populacional

O modelo de crescimento populacional acima é bem simples e elegante, mas também pouco realista. Esse modelo prevê que o tamanho de uma população seguindo esse tipo de trajetória de crescimento exponencial tenderá ao infinito. Como isso é obviamente impossível na natureza, devemos aprimorar esse modelo. Isso pode ser feito reavaliando algumas premissas do modelo acima, especificamente as premissas de que as taxas de natalidade ($b$) e mortalidade ($d$) per capita são independentes do tamanho populacional ($N$). Podemos, por exemplo, assumir que a taxa de crescimento per capita diminua linearmente com $N$ até chegar a zero. O tamanho $N$ de uma população que chega a esse ponto, em que a população pára de crescer e estabiliza ($dN/dT = 0$), é conhecido como capacidade de suporte ($K$). A dinâmica de uma população com crescimento limitado pode ser modelada através de uma equação de crescimento logística como esta:

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

Podemos ver que quando $N$ se iguala a $K$, a taxa de crescimento populacional é zerada. Da mesma forma, sempre que o valor de $N$ for maior que $K$, a taxa de crescimento populacional se torna negativa, até que a população retorne à capacidade de suporte.

Crescimento logístico defasado

Em algumas situações, a taxa de crescimento de uma população leva um tempo (atraso) para responder à mudança de tamanho dessa população. Por exemplo, quando a reprodução ou sobrevivência de indivíduos adultos depende da quantidade de recursos que tiveram acesso quando ainda imaturos, as taxas de natalidade e mortalidade podem refletir uma condição ambiental que não existe mais. Ou seja, a população pode continuar crescendo ou diminuindo mesmo após ter chegado à sua capacidade de suporte. Podemos modelar esse cenário fazendo com que a taxa de crescimento populacional no tempo $t$ seja uma função do tamanho populacional num tempo pretérito ($t-\tau$):

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

Tabela de parâmetros

pars_vars <- c("$r_i$", 
               "$K_i$", 
               "$N_i$",
               "$\\tau$")
descriptions <- c("taxa de crescimento intrínseco",
                 "capacidade de suporte",
                 "tamanho populacional",
                 "tempo de atraso (modelo logístico defasado)")
param_df <- data.frame(pars_vars, descriptions)
kable(x = param_df, format = "html", 
      col.names = c("Parâmetro/variável", "Descrição")) %>%
  kable_styling(full_width = FALSE, 
                bootstrap_options = c("striped", "hover", "condensed"),
                position = "center")

Aplicativo interativo

sidebarLayout(
  sidebarPanel(
    # User defined density dependent or independent growth ----
    radioButtons("densdep", "Tipo de crescimento populacional", 
                 choices = c(`Denso independente` = "indep", `Denso dependente` = "dep")),

    # User defined intrinsic growth rate r -----
    sliderInput("r_val", label = "Taxa de crescimento intrínseca (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 = "Capacidade de suporte (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 = "denso-dependência atrasada?",
                                  choices = c(`No` = "nolag",`denso dependência atrasada` = "lag"))),

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

    # User defined initial population size  -----
    sliderInput("N1_val", label = "Tamanho inicial da população::",
                min = 1, max = 1000, value = 50, step = 10),
    hr(),

    # User can add a second species ----
    checkboxInput("secondsp", "Adicione uma segunda espécie?", 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", "Tipo de crescimento populacional para a segunda espécie:", 
                                  choices = c(`Denso independente` = "indep", `Denso dependente` = "dep")),

                     # User defined intrinsic growth rate r2 -----
                     sliderInput("r_val2", label = "Taxa de crescimento intrínseca da espécie 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 = "Capacidade de suporte da espécie 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 = "denso-dependência atrasada?",
                                  choices = c(`No` = "nolag",`denso dependência atrasada` = "lag"))),

                     # If timelag requested in density-dependent growth, ask for tau -----
                     conditionalPanel(condition = "input.densdepLag2 == 'lag'",
                                      sliderInput("tau2", label = "tempo de atraso (tau2)",
                                                  min = 0, max = 4, value = 1, step = .1)),
                     sliderInput("N2_val", label = "Tamanho inicial da população para a espécie 2:",
                                 min = 1, max = 1000, value = 50, step = 10),
                         hr()),

    # User can select which plots to show ----
    checkboxGroupInput("plots_to_show", "Escolha os gráficos que quer ver:",
                       c("N ao longo do tempo" = "Nvtime",
                         "ln(N) ao longo do tempo" = "lnNvtime",
                         "crescimento populacional em função de N" = "n1overn",
                         "crescimento populacional per capita em função de N" = "n1novern"), selected = c("Nvtime", "lnNvtime")),
    hr(),

    # User defined length of simulation -----
    numericInput("max_time", label = "duração da simulação:",
                value = 100),

                     # User defined initial population size  -----
    ),



  # 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("Species 1 parameter values: r1 = ", input$r_val)
  } else if (input$densdepLag == "nolag") { 
    paste0("Species 1 parameter values: r1 = ", input$r_val, ", K1 = ", input$K_val) 
    } else { 
    paste0("Species 1 parameter values: r1 = ", input$r_val, ", K1 = ", input$K_val, ", Tau1 = ", input$tau) 
    }
})

plot_caption2 <- reactive({
  if(input$secondsp) {
    if(input$densdep2 == 'indep') {
      paste0("Species 2 parameter values: r2 = ", input$r_val2)
    } else if (input$densdepLag2 == "nolag") { 
      paste0("Species 2 parameter values: r2 = ", input$r_val2, ", K2 = ", input$K_val2) 
    } else { 
      paste0("Species 2 parameter values: 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("Species", palette = "Set1") +
      ylab("Population size") 
    } 
})

# 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("Species", 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(Population size)") 
    }
})

# 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("Population Size") + 
      ylab("Population growth rate (dN/dt)") + 
      scale_color_brewer("Species", 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("Population Size") + 
      ylab("per-capita population growth rate\n(dN/Ndt)") + 
      scale_color_brewer("Species", 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')
})

Leituras recomendadas

"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 = "pt"))


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