10  Propiedades de las matrices y estimación de parámetros

Por: Mariana Hernández-Apolinar y Paola Portillo Tzompa

Las propiedades de una matriz de proyección poblacional determinan cómo se comporta una población a largo plazo bajo condiciones constantes. Este capítulo introduce las principales propiedades matemáticas y biológicas de las matrices poblacionales y explica por qué son centrales para interpretar la dinámica poblacional más allá del valor de λ.

10.1 Propiedades fundamentales de las matrices de proyección poblacional

Las matrices de proyección poblacional poseen un conjunto de propiedades matemáticas que gobiernan la dinámica demográfica de las poblaciones a largo plazo. Entre estas propiedades se encuentran la estructura estable por estadios, el valor propio dominante (λ), el vector reproductivo y la convergencia asintótica de la población hacia un patrón dinámico estable.

En este capítulo se examinan estas propiedades desde una perspectiva biológica, mostrando cómo emergen de la estructura del ciclo de vida y de las tasas vitales que describen supervivencia, crecimiento y fecundidad. Se explica cómo la estructura estable de la población representa la distribución proporcional de individuos entre estadios cuando la población ha alcanzado su dinámica asintótica, y por qué esta estructura es clave para interpretar proyecciones poblacionales y comparaciones entre escenarios.

Además, se introduce el concepto de valor reproductivo como una medida de la contribución relativa de cada estadio al crecimiento futuro de la población. Este capítulo se diferencia de los anteriores porque no se centra en el cálculo de λ ni en su sensibilidad a cambios paramétricos, sino en la comprensión de las propiedades estructurales que explican por qué las poblaciones exhiben determinados patrones de crecimiento, estabilidad o declive. Estas propiedades constituyen la base conceptual para análisis posteriores de elasticidad, LTRE y simulaciones poblacionales.

10.2 Propiedades matemáticas y cálculo computacional

A continuación se ilustran las propiedades matemáticas de las matrices de proyección poblacional y su cálculo mediante herramientas computacionales.

10.2.0.1 Librerías de R requeridas para el siguiente módulo

Código
library(popdemo)
library(popbio)
library(ggplot2)
library(dplyr)
library(scales)
library(Rage)

10.3 Propiedades, supuestos e índices matriciales

En este capítulo aprenderemos sobre algunos índices que se usan con frecuencia en el análisis matricial. Estos índices nos ayudan a saber si una matriz es “buena” para trabajar y si los resultados que obtenemos son confiables.

El capítulo está dividido en dos partes:

  1. Índices sobre el estado de la matriz

Aquí veremos características básicas que debe cumplir una matriz para que el análisis sea válido:

  • Dimensión cuadrada: la matriz debe tener el mismo número de filas y columnas.
  • Ergocidad: asegura que, con el tiempo, todas las partes del sistema se conecten.
  • No negatividad: los valores de la matriz no pueden ser negativos.
  • Irreducibilidad: indica que no se puede dividir la matriz en bloques independientes.
  • Primitividad: garantiza que, después de varias iteraciones, la matriz se estabiliza.
  1. Índices sobre el comportamiento a largo plazo

Estos se basan en modelos de proyección poblacional (MPP) y nos permiten entender cómo cambia la población antes y después de un disturbio:

  • Análisis de convergencia: mide si la población tiende a una estructura estable.
  • Análisis de amortiguamiento: indica qué tan rápido se alcanza esa estabilidad.
  • Valor reproductivo: muestra la importancia de cada clase en la reproducción futura.
  • Estructura estable: describe la distribución de la población cuando todo se estabiliza.

Si quieres profundizar en estos índices, te recomiendo consultar (Caswell, 2001) y (Stott, Townley & Hodgson, 2011).

10.4 Construcción de una matriz poblacional

El primer paso en el análisis matricial es construir una matriz de transición poblacional, la cual resume en una tabla la supervivencia,la reproducción y transiciones de los individuos en diferentes etapas o categorías de edad. Cada fila y columna de la matriz representa un estadio del ciclo de vida de la especie, y cada elemento dentro de la matriz describe la transición de un estadio a otro en un intervalo de tiempo determinado (por ejemplo, de un año a otro).

10.5 Matriz de proyección poblacional (MPP)

Una matriz de proyección poblacional (MPP) es una matriz cuadrada que permite describir y predecir la dinámica de una población a través del tiempo. En esta se organizan las probabilidades de transición entre categorías de tamaño o estado (plántulas, juveniles, adultos, etc.) junto con la fecundidad o reproducción de los individuos.

La MPP se utiliza para proyectar la estructura de una población en el futuro, a partir de su composición actual. Así, constituye la base para calcular tasas de crecimiento poblacional, estructuras estables, valores reproductivos y otros índices demográficos fundamentales.

A continuación se construye la matriz poblacional de Lepanthes rubripetala. Esta matriz se compone de cuatro estados: plántulas (PL), juveniles (J), adultos no reproductivos (NR) y adultos reproductivos (AR).

Código
# Capturar los datos de la matriz para L. rubripetala
# (Tremblay et al. 2015)
Lr1 <- matrix(c(0.4324, 0, 0, 0.15, 0.3784, 0.8459, 0, 0, 0,
    0.0034, 0.7954, 0.23, 0, 0.089, 0.1841, 0.751), byrow = TRUE,
    ncol = 4)

# Capturar las categorias de estado
estadios <- c("PL", "J", "NR", "AR")
colnames(Lr1) <- rownames(Lr1) <- estadios

# Obtener la matriz L. rubripetala
Lr1 <- matrix(Lr1[1:4, ], nrow = 4, dimnames = list(estadios,
    estadios))
Lr1
       PL      J     NR    AR
PL 0.4324 0.0000 0.0000 0.150
J  0.3784 0.8459 0.0000 0.000
NR 0.0000 0.0034 0.7954 0.230
AR 0.0000 0.0890 0.1841 0.751

10.6 Supuestos de la matriz poblacional

10.6.1 Dimensión cuadrada

Las matrices poblacionales deben tener dimensiones cuadradas, es decir, deben tener el mismo número de renglones que de columnas. Esta característica es importante porque cada columna y renglón representa una categoría de edad o un estado del ciclo de vida de la especie. Las columnas representa categoría de los individuos al inicio del estudio, mientras que los renglones su tránsito a otra después de un periodo de tiempo. Si la matriz no es cuadrada, no hay correspondencia que permita comparar el número de individuos por categoría al inicio y final de un periodo de estudio, por lo que será imposible estimar la tasa de crecimiento poblacional. En el caso de L. rubripetala, la matriz poblacional tiene 4 renglones y 4 columnas, por lo que cumple con la propiedad de dimensión cuadrada. Esto puede verificarse fácilmente en R usando la función dim.

Código
dim(Lr1)
[1] 4 4

10.6.2 Ergócidad

Decimos que la propiedad de ergodicidad se cumple cuando el crecimiento asintótico predicho por matriz es independiente de la estructura poblacional inicial considerada en el estudio. En otras palabras, sin importar el estado inicial de la población, su comportamiento converge a una estructura estable y a una tasa de crecimiento constante a largo plazo. Si una matriz poblacional no es ergódica, el crecimiento poblacional depende de la estructura poblacional inicial, lo que implica que el promedio o la tasa de crecimiento poblacional no son buenos predictores del comportamiento poblacional a largo plazo (Mangalam & Kelty-Stephen, 2022). Para comprobar si la matriz es ergódica puede emplearse la función isErgodic del paquete popbio en R. Esta función da como resultado el valor lógico “TRUE” si la matriz es ergódica y “FALSE” en el caso contrario. En L. rubripetala se espera que la matriz sea ergódica, ya que los autores reportaron que la población alcanza tanto una estructura estable como una tasa de crecimiento constante en el tiempo (Tremblay, Raventos & Ackerman, 2015).

Código
isErgodic(Lr1, digits = 5, return.eigvec = FALSE)
[1] TRUE

Una matriz no cumple la condición de ergodicidad cuando, por ejemplo, ningún individuo logra pasar del estado de plántula al juvenil ni al adulto. En este caso, la población queda “atascada” en las primeras etapas y no puede alcanzar una estructura estable. Si evaluamos esta matriz con la función isErgodic del paquete popbio en R, el resultado será FALSE. Esto indica que:

  • El crecimiento poblacional depende de la estructura inicial, y
  • No se puede esperar que la población alcance una estructura estable ni una tasa de crecimiento constante a largo plazo.
Código
# Capturar los datos de la matriz para L. rubripetala
# (Tremblay et al. 2015)
Lr1_No_erg <- matrix(c(0.4324, 0, 0, 0.15, 0, 0.8459, 0, 0, 0,
    0.0034, 0.7954, 0.23, 0, 0.089, 0.1841, 0.751), byrow = TRUE,
    ncol = 4)

plot_life_cycle(Lr1_No_erg, stages = estadios, fontsize = 8)
Código
isErgodic(Lr1_No_erg, digits = 4, return.eigvec = FALSE)
[1] FALSE

10.6.3 Elementos no negativa

Una matriz poblacional debe ser no negativa, lo que significa que todas sus entradas son mayores o iguales a cero. ¿Por qué? Porque cada valor representa el número o la proporción de individuos que pasan de una etapa a otra. Tener valores negativos no tendría sentido biológico: no puede haber “menos” individuos que los existentes.

Además, si la matriz tuviera elementos negativos:

  • No podríamos comparar correctamente las categorías de edad o estado.
  • Sería imposible calcular la tasa de crecimiento poblacional.

En el caso de L. rubripetala, la matriz cumple esta condición, ya que todos sus valores son mayores o iguales a cero. En R, esto se puede verificar con la función isPositive, que devuelve:

  • TRUE si la matriz es no negativa,
  • FALSE si contiene algún valor negativo
Código
# No negativa

IsPositive <- function(mat) {
    if (all(mat >= 0)) {
        return(TRUE)
    } else {
        return(FALSE)
    }
}

IsPositive(Lr1)
[1] TRUE

A continuación se muestra un ejemplo de una matriz que no cumple la propiedad de no negatividad. En este caso, el elemento ubicado en la posición (4, 3) es negativo, lo que indica que la transición desde la categoría adulto reproductivo hacia adulto no reproductivo tiene un valor inválido.

Al evaluar esta matriz con la función isPositive en R, el resultado es FALSE. Esto significa que:

  • La matriz no es válida para el análisis de dinámica poblacional.
  • No se puede esperar que la población alcance una estructura estable ni una tasa de crecimiento constante a largo plazo.
Código
# Capturar los datos de la matriz para L. rubripetala
# (Tremblay et al. 2015)
Lr1_No_pos <- matrix(c(0.4324, 0, 0, 0.15, 0.3784, 0.8459, 0,
    0, 0, 0.0034, 0.7954, -0.23, 0, 0.089, 0.1841, 0.751), byrow = TRUE,
    ncol = 4)

IsPositive(Lr1_No_pos)
[1] FALSE

10.6.4 Irreducibilidad

Una matriz de transición poblacional debe ser irreducible, lo que significa que todas sus categorías están conectadas y existe al menos una ruta que permite llegar desde cualquier estado a los demás. Esta propiedad es esencial porque, si la matriz no es irreducible, la población no podrá alcanzar una estructura estable ni una tasa de crecimiento constante a largo plazo.

En el caso de L. rubripetala, la matriz es irreducible: todas las etapas del ciclo de vida están conectadas y existe una ruta entre ellas. Para comprobar esta propiedad en R, se utiliza la función isIrreducible del paquete popdemo, que devuelve:

  • TRUE si la matriz es irreducible,
  • FALSE si no lo es.

Es importante destacar que no todas las matrices reducibles son inválidas. En algunos casos, pueden aceptarse, por ejemplo, en especies con etapas que no influyen en el crecimiento poblacional, como las fases postreproductivas en mamíferos (humanos, ballenas, etc.).

En resumen, para L. rubripetala, la función isIrreducible devuelve TRUE, lo que confirma que todas las categorías están conectadas y que la población puede alcanzar una estructura estable y una tasa de crecimiento constante a largo plazo.

Código
isIrreducible(Lr1)
[1] TRUE

A continuación se muestra un ejemplo de matriz en la que el cuarto estadio no presenta valores de reproducción. Al evaluar esta matriz con la función isIrreducible en R, el resultado es FALSE.

¿Por qué ocurre esto? Porque no existe un vínculo entre la categoría plántula y la categoría adulto reproductivo, lo que significa que la presencia de plántulas en la población no contribuye a la reproducción.

Esta ausencia de conexión provoca dos problemas:

  • Un ciclo de vida incompleto, como se observa en la imagen.
  • Una población que no podrá alcanzar una estructura estable ni una tasa de crecimiento constante a largo plazo.
Código
Lr1_Irr <- matrix(c(0.4324, 0, 0, 0, 0.3784, 0.8459, 0, 0, 0,
    0.0034, 0.7954, 0.23, 0, 0.089, 0.1841, 0.751), byrow = TRUE,
    ncol = 4)

plot_life_cycle(Lr1_Irr, stages = estadios, fontsize = 8)
Código
isIrreducible(Lr1_Irr)
[1] FALSE

10.6.5 Primitividad

Una matriz de transición poblacional debe ser primitiva, lo que significa que, al elevarla a potencias altas, se obtiene un único valor positivo dominante (la tasa de crecimiento poblacional). Esta propiedad es clave porque asegura que la población alcanzará una estructura estable y una tasa de crecimiento constante a largo plazo.

En el caso de L. rubripetala, la matriz es primitiva: al elevarla a potencias altas, aparece un único valor positivo. En R, esto se puede comprobar con la función isPrimitive del paquete popdemo, que devuelve:

  • TRUE si la matriz es primitiva,
  • FALSE si no lo es.

Una matriz no primitiva tendría una dinámica inestable a largo plazo, como ocurre en poblaciones con comportamiento cíclico, donde las proporciones entre categorías oscilan sin llegar a estabilizarse.

Es importante señalar que:

  • Toda matriz irreducible es primitiva,
  • Pero no toda matriz primitiva es irreducible. Por ejemplo, una matriz puede ser primitiva sin ser irreducible si incluye un ciclo de vida completo, pero alguna etapa no influye en el crecimiento poblacional (como fases postreproductivas).
Código
isPrimitive(Lr1)
[1] TRUE

10.7 Índices de descripción de la matriz poblacional

En esta sección se revisan los índices poblacionales obtenidos a partir del análisis de matricial, los cuales se estiman una vez que ha verificado que cumplen con los supuestos. Estos índices permiten comprender el comportamiento de la población a largo plazo y anticipar cómo se espera que se comporte en el tiempo. Los índices que se abordan a continuación son: estructura estable, valor reproductivo, análisis de convergencia y análisis de amortiguamiento. Todos estos se calculan a partir de la matriz de transición poblacional y del vector de la estructura poblacional observada al inicio del estudio.


10.7.1 Estructura estable

La estructura poblacional estable (W, también conocida como eigenvector derecho) indica la proporción esperada de individuos en cada categoría de edad o estado cuando la población ha alcanzado el equilibrio a largo plazo. Por ejemplo, en L. rubripetala se espera que la estructura estable sea:

  • Plántulas: 0.088
  • Juveniles: 0.206
  • Adultos no reproductivos: 0.369
  • Adultos reproductivos: 0.337

Este índice supone que la tasa de crecimiento poblacional (\(\lambda\)) se mantiene constante en el tiempo, lo cual solo ocurre bajo condiciones ambientales estables. Sin embargo, en la naturaleza esto es poco común. Además, la estructura estable asume que el periodo de muestreo y las condiciones abióticas y bióticas son típicas y no cambian.

En la revisión de Williams y colaboradores (Williams et al., 2011), se reportó que más del 80% de las poblaciones analizadas no cumplían con la condición de estructura estable, especialmente en especies con matrices grandes (n × n) y tiempos generacionales prolongados. De manera similar, Tremblay (com. pers.) observó que la mayoría de las orquídeas estudiadas no estaban en estructura estable al inicio del muestreo poblacional.

Código
# Estructura estable de estados

stable.stage(Lr1)
        PL          J         NR         AR 
0.08789851 0.20619682 0.36907404 0.33683063 

Uno puede visualizar la estructura poblacional usando el código siguiente.

Código
Wmax <- stable.stage(Lr1)
Wdf = data.frame(Wmax)
Wdf$Categorias = c("Plántulas", "Juveniles", "Adultos no reproductivos",
    "Adultos reproductivos")
Wdf$Categorias = factor(Wdf$Categorias, levels = c("Plántulas",
    "Juveniles", "Adultos no reproductivos", "Adultos reproductivos"))
library(ggplot2)

ggplot(Wdf, aes(y = Wmax, x = Categorias)) + geom_bar(stat = "identity",
    aes(fill = "blue")) + labs(title = "Estructura estable de estados esperada",
    x = "Etapas", y = "Proporción") + rlt_style_fill() + theme(axis.text.x = element_text(angle = 45,
    hjust = 1)) + theme(legend.position = "null")


10.7.2 Valor reproductivo

Spathoglottis plicata. Foto: Tremblay

El valor reproductivo (v, también llamado eigenvector izquierdo) indica la contribución esperada de cada categoría de edad o estado a la reproducción de la población.

En el caso de L. rubripetala, los valores reproductivos esperados son:

  • Plántulas: 1.00
  • Juveniles: 1.52
  • Adultos no reproductivos: 2.32
  • Adultos reproductivos: 2.66

Este índice es muy útil porque muestra qué etapas son más importantes para el crecimiento poblacional a largo plazo. La primera categoría siempre tiene un valor de 1.00, ya que representa el inicio del ciclo de vida y sirve como referencia para calcular los demás valores.

Además, el valor reproductivo ayuda a definir estrategias de manejo. Por ejemplo:

  • En Spathoglottis plicata, una orquídea terrestre invasora, las acciones de control deberían enfocarse en las categorías con mayor valor reproductivo, porque son las que más contribuyen al crecimiento poblacional.

  • Por el contrario, si se busca remover individuos con el menor impacto posible, conviene actuar sobre las etapas con valores reproductivos bajos.

Código
# Valor reproductivo

reproductive.value(Lr1)
      PL        J       NR       AR 
1.000000 1.519043 2.316113 2.664676 

10.7.3 Análisis de convergencia y amortigamiento (“Damping ratio”)

El análisis de convergencia mide el tiempo esperado para que una población alcance su estructura estable y un crecimiento asintótico después de un disturbio. Es decir, indica qué tan rápido la población regresa a su estructura estable tras una perturbación (Stott, Townley & Hodgson, 2011). Este comportamiento se cuantifica mediante el índice de amortiguamiento (damping ratio), que evalúa la influencia del valor propio subdominante, \(\lambda_2\), durante el periodo de convergencia.

El índice se expresa a través del cociente entre el valor propio dominante, \(\lambda_1\), y el valor absoluto del subdominante \[\mathbf{\rho=\frac{\lambda_1}{\left|\lambda_2\right|}}\]; dónde \(\rho\) representa el índice de amortiguamiento, \(\lambda_1\) corresponde al valor propio dominante de la matriz de transición poblacional y \(\lambda_2\) al módulo del segundo valor propio más grande. Este índice no tiene unidades y es independiente de la estructura inicial de la población.

En el caso de L. rubripetala, al calcular los valores propios de la matriz con la función eigen, se obtiene un valor dominante de \(\lambda_1= 1.00721\) y un valor subdominante de \(\lambda_2= 0.8319\). De esta manera el índice de amortiguamiento es:

\[ \rho = \frac{\lambda_1}{|\lambda_2|} = \frac{1.00721}{|0.83192|} \approx 1.21 \]

El valor obtenido indica que la población converge hacia su estructura estable tras un disturbio; aunque, lentamente.

Es importante señalar que la interpretación de este índice depende de la escala temporal con que se construyó la matriz. Si bien la mayoría de los estudios poblacionales utilizan datos anuales (Crone et al., 2011), también existen estudios con periodos de muestreo mensuales, bimensuales, estacionales o bianuales, los cuales se establecen de acuerdo con el ciclo de vida de la especie estudiada.

Código
eigen(Lr1)$values  # la lista de valores propios de la matriz Lr1
[1] 1.0072061+0.00000000i 0.8319189+0.00000000i 0.4927875+0.06468183i
[4] 0.4927875-0.06468183i
Código
DR = eigen(Lr1)$values[1]/abs(eigen(Lr1)$values[2])

DR
[1] 1.210702+0i
Código
dr(Lr1)  # usando la función 'dr' para 'damping ratio' en el paquete 'popdemo'
[1] 1.210702

10.7.4 Graficación del índice de amortiguamiento

El comportamiento del índice de amortiguamiento se puede visualizar mediante una gráfica de líneas, que muestra cómo responde un sistema ante un cambio súbito (un “paso de entrada”) y cómo varía esa respuesta en el tiempo según diferentes niveles de amortiguamiento.

Para facilitar la comprensión, en el siguiente bloque se incluye el código que genera una gráfica ilustrando el comportamiento de una población perturbada:

Código
library(ggplot2)

# --- Definir los parametros --- Población inicial en el
# tiempo t=0. Ese el punto de equilibrio inicial.
poblacion_inicial <- 1000

# Factores de amortiguamiento para graficar.  0,3 =
# Subamortiguado (oscila) 1,0 = Críticamente amortiguado
# (retorno más rápido sin oscilación) 2,0 =
# Sobreamortiguado (retorno lento sin oscilación)
amortigamento <- c(0.3, 1, 2, 3)

# Frecuencia de la oscilación (omega_n).
frecuencia <- 0.5

# Tiempo total para la simulación
tiempo_total <- 50

# Paso de tiempo para la simulación (más pequeño para una
# curva más suave)
etapa_tiempo <- 0.1

# --- Generate the Damped Oscillation Data for Multiple
# Ratios --- Create an empty data frame to store all the
# data
todo_data_df <- data.frame()

# Recorra cada relación de amortiguamiento para generar los
# datos
for (zeta in amortigamento) {
    # Create a sequence of time points
    time_points <- seq(0, tiempo_total, by = etapa_tiempo)

    # Calculate the population at each time point based on
    # the damping ratio.  The mathematical form of the step
    # response changes depending on the damping ratio.

    if (zeta < 1) {
        # Underdamped case: damped sine wave
        omega_d <- frecuencia * sqrt(1 - zeta^2)
        population_data <- poblacion_inicial * (1 - exp(-zeta *
            frecuencia * time_points) * (cos(omega_d * time_points) +
            (zeta/sqrt(1 - zeta^2)) * sin(omega_d * time_points)))
    } else if (zeta == 1) {
        # Critically Damped case
        population_data <- poblacion_inicial * (1 - exp(-frecuencia *
            time_points) * (1 + frecuencia * time_points))
    } else {
        # Overdamped case
        s1 <- -zeta * frecuencia + frecuencia * sqrt(zeta^2 -
            1)
        s2 <- -zeta * frecuencia - frecuencia * sqrt(zeta^2 -
            1)
        population_data <- poblacion_inicial * (1 - (s2 * exp(s1 *
            time_points) - s1 * exp(s2 * time_points))/(s2 -
            s1))
    }

    # Add the data for the current damping ratio to a
    # temporary data frame
    temp_df <- data.frame(Time = time_points, Population = population_data,
        DampingRatio = factor(zeta)  # Store damping ratio as a factor for coloring
)

    # Bind the temporary data frame to the main data frame
    todo_data_df <- rbind(todo_data_df, temp_df)
}

# --- Create the Plot using ggplot2 ---
ggplot(todo_data_df, aes(x = Time, y = Population, color = DampingRatio)) +
    # Add the lines for each damping ratio
geom_line(linewidth = 1.2) + # Set the title and labels geom_line(linewidth
geom_line(linewidth = 1.2) + # Set the title and labels =
geom_line(linewidth = 1.2) + # Set the title and labels 1.2)
geom_line(linewidth = 1.2) + # Set the title and labels + #
geom_line(linewidth = 1.2) + # Set the title and labels Set
geom_line(linewidth = 1.2) + # Set the title and labels the
geom_line(linewidth = 1.2) + # Set the title and labels title
geom_line(linewidth = 1.2) + # Set the title and labels and
geom_line(linewidth = 1.2) + # Set the title and labels labels
labs(title = "El efecto de amortigamento \n sobre el tamaño de población",
    subtitle = "La población se estabiliza a un equilibrio de 1000",
    x = "Tiempo", y = "Tamaño poblacional", color = expression("Amortigamento (" *
        zeta * ")")) + # Customize the plot theme for better aesthetics zeta
        zeta * ")")) + # Customize the plot theme for better aesthetics *
        zeta * ")")) + # Customize the plot theme for better aesthetics ")"))
        zeta * ")")) + # Customize the plot theme for better aesthetics +
        zeta * ")")) + # Customize the plot theme for better aesthetics #
        zeta * ")")) + # Customize the plot theme for better aesthetics Customize
        zeta * ")")) + # Customize the plot theme for better aesthetics the
        zeta * ")")) + # Customize the plot theme for better aesthetics plot
        zeta * ")")) + # Customize the plot theme for better aesthetics theme
        zeta * ")")) + # Customize the plot theme for better aesthetics for
        zeta * ")")) + # Customize the plot theme for better aesthetics better
        zeta * ")")) + # Customize the plot theme for better aesthetics aesthetics
rlt_style_colour() + theme_minimal(base_size = 14) + theme(plot.title = element_text(hjust = 0.5,
    face = "bold"), plot.subtitle = element_text(hjust = 0.5),
    axis.title = element_text(face = "bold"))
Error in parse(text = input): <text>:85:19: unexpected ')'
84:         zeta * ")")) + # Customize the plot theme for better aesthetics zeta
85:         zeta * ")")
                      ^

10.7.5 Intepretación del gráfico de amortiguamiento

La figura resultante ilustra el efecto de diferentes coeficientes de amortiguamiento en la respuesta de una población a un cambio súbito. El gráfico muestra cuatro comportamientos distintos para la población perturbada y su retorno a un estado de equilibrio, correspondiente a un tamaño poblacional de 1000 individuos.

La respuesta de la población ante cuatro índices de amortiguamiento es la siguiente:

• Subamortiguado (ζ=0.3): Esta es la respuesta oscilante. El sistema sobrepasa el punto de equilibrio y luego oscila, con el tiempo la amplitud de las oscilaciones disminuyen gradualmente hasta estabilizarse en el equilibrio.

• Amortiguado críticamente (ζ=1.0): Esta es la respuesta más rápida, la cual alcanza el equilibrio sin oscilaciones ni sobreamortiguaciones. Se considera la respuesta ideal para sistemas que requieren un retorno rápido y estable al valor objetivo.

• Sobreamortiguado (ζ=2.0): Esta respuesta es lenta y se aproxima al punto de equilibrio sin oscilaciones. En comparación con el caso críticamente amortiguado, tarda mucho más en estabilizarse, ya que la fuerza de amortiguamiento es muy grande.

• Sobreamortiguado (ζ=3.0): Similar al caso anterior, pero con un amortiguamiento aún mayor. La respuesta es muy lenta y se acerca al equilibrio de manera gradual sin oscilaciones.

10.7.5.1 Tiempo de Convergencia

El tiempo de convergencia es el periodo estimado que tarda la población en alcanzar su estructura estable. Este índice es relevante porque facilita entender el comportamiento poblacional a largo plazo. En R este cálculo puede realizarse con dos funciones del paquete popdemo: dr y convt. La función dr calcula el amortiguamiento y a partir de éste puede estimarse el tiempo de la convergencia de la siguiente manera:

\[ t = \frac{\log(dr)}{\log(x)} \]

dónde

  • \(dr\) es el índice de amortiguamiento (damping ratio)
  • \(x\) es un factor de comparación
  • \(t\) representa el tiempo en la misma unidad en que se construyó la matriz (días, meses, años, etc.).

El análisis de amortiguamiento estima la rapidez con la que una población converge a su estructura estable después de un disturbio (Jiang et al., 2020). El índice de amortiguamiento (\(d > 0\)) sugiere que mientras mayor sea su valor, más rápida será la convergencia. El tiempo de amortiguamiento se calcula como: \(\tau=1/d\), dónde \(\tau\) expresa la duración del proceso de convergencia en unidades de tiempo consistentes con la matriz poblacional. Cabe señalar que, se ha demostrado que existe una relación entre el índice de amortiguamiento y el tiempo generacional de una especie (Jiang et al., 2020).

Código
dr(Lr1, return.time = TRUE, x = 10)  # cuanto tiempo toma aumentar la población de veces 
$dr
[1] 1.210702

$t
[1] 12.04278

A partir de la la función \(contv\) del paquete popdemo se puede estimar el tiempo esperado en que una población alcanza su estructura estable, considerando la estructura poblacional observada al inicio del estudio. Esta función simula el modelo y determina manualmente cuándo la población converge, dado un nivel de exactitud especifico (accuracy). Entre más estricta sea la exactitud, mayor será el tiempo de convergencia. Para utilizar esta función es necesario indicar la estructura inicial, es decir, el número de individuos en cada estadio. En el caso de L. rubripetala se espera que el tiempo de convergencia sea de 18 ciclos (meses) para alcanzar su estructura estable.

Por ejemplo, si se comienza con una población inicial de 8, 20, 27 y 34 individuos en las categorías de plántulas, juveniles, adultos no reproductivos y adultos reproductivos, respectivamente, la población alcanzaría en 6 meses, aproximadamente, la estructura estable. En contraste, si la población inicial estuviera sesgada (compuesta únicamente por plántulas, por ejemplo), el tiempo de convergencia sería mucho mayor. Este enfoque resulta muy útil al definir estrategias de conservación; por ejemplo, al establecer una nueva población con una distribución inicial determinada.

Código
n0 <- c(8, 20, 27, 34)  # la estructura de la población inicial

convt(Lr1, accuracy = 1e-04, vector = n0, iterations = 10000)  # la estructura poblacional inicial
[1] 18

Dado que el tiempo de convergencia es un índice que representa el periodo esperado para que una población alcance su estructura estable, se puede calcular variando la cantidad de individuos en las diferentes edades o estados al llevar a cabo una simulación.

Por ejemplo, se estima que L. rubripetala alcanzaría la estructura estable en 25 meses, si la población inicia con una población sesgada a plántulas (n = 1000) y, por lo tanto, sin la presencia de individuos de los estados posteriores.

10.7.6 Graficación del tiempo de convergencia al estado estable de cada etapa de vida

La población comienza en cada etapa con 100 individuos y se simula durante 22 pasos de tiempo. El gráfico resultante muestra cómo la población converge a su estructura estable a lo largo del tiempo, con cada etapa representada por una línea de color diferente. La línea horizontal indica el valor de la proporción de la etapa estable y la linea vertical representa a que tiempo se espera que la etapa llegua a su nivel de estructura estable.

Nota que si las condiciones se quedan igual en el tiempo se espera que la población converja a una estructura estable, es decir, que la proporción de individuos en cada etapa se mantenga constante a lo largo del tiempo. En este caso, la proporción de individuos en cada etapa converge a 0.088, 0.206, 0.369 y 0.337 para las categorías de plántulas, juveniles, adultos no reproductivos y adultos reproductivos, respectivamente 3, 17, 15 y 9 periodos (el tiempo de re-muestreo correspondiente a la construcción de la matrix).

Código
# Este script utiliza un enfoque de matriz para modelar las
# dinámicas de una población de 4 etapas (por ejemplo,
# clases de edad o estadios de vida).  Demuestra cómo una
# distribución de población converge a un estado estable.

# Instalar y cargar el paquete ggplot2 para el trazado
# install.packages('ggplot2')
library(ggplot2)

# --- Definir Parámetros de Simulación --- Población
# inicial en el tiempo t=0 para cada etapa.  Una
# distribución inicial uniforme es un buen punto de partida
# para observar la convergencia.
initial_population <- c(100, 100, 100, 100)

# Número total de pasos de tiempo para la simulación
total_time_steps <- 22

# --- Definir la Matriz de Transición de la Población
# (Leslie Matrix) --- Se utiliza la matriz proporcionada
# por el usuario.
transition_matrix <- matrix(c(0.4324, 0, 0, 0.15, 0.3784, 0.8459,
    0, 0, 0, 0.0034, 0.7954, 0.23, 0, 0.089, 0.1841, 0.751),
    nrow = 4, byrow = TRUE)

# --- Simular la Dinámica de la Población y Calcular
# Proporciones --- Nombres de las etapas en el orden
# especificado
stage_names <- c("juvenil", "plántula", "adulto no reproductivo",
    "adulto reproductivo")

# Crear un data frame para almacenar los resultados de la
# simulación
all_data_df <- data.frame(Time = integer(), Proportion = numeric(),
    Stage = character())

# Vector de población actual (distribución inicial)
n_current <- initial_population

# Bucle para simular cada paso de tiempo
for (t in 0:total_time_steps) {
    # Calcular la proporción de la población en cada etapa
    current_proportions <- n_current/sum(n_current)

    # Crear un data frame temporal para este paso de tiempo
    temp_df <- data.frame(Time = rep(t, 4), Proportion = current_proportions,
        Stage = factor(stage_names, levels = stage_names)  # Se usa factor para ordenar las etapas
)

    # Añadir los datos al data frame principal
    all_data_df <- rbind(all_data_df, temp_df)

    # Proyectar la población al siguiente paso de tiempo
    # Multiplicación de la matriz de transición por el
    # vector de población
    n_next <- transition_matrix %*% n_current
    n_current <- n_next
}
# --- Calcular la Distribución de Etapa Estable (SSD) ---
# Se calcula el vector propio derecho (eigenvector) del
# valor propio dominante.  Este vector representa la
# proporción de individuos en cada etapa en el estado
# estable.
eigen_results <- eigen(transition_matrix)

# Encontrar el valor propio dominante (más grande)
dominant_eigenvalue <- max(Re(eigen_results$values))

# Encontrar el vector propio derecho correspondiente
# (eigenvector)
stable_stage_distribution_raw <- Re(eigen_results$vectors[, which.max(Re(eigen_results$values))])

# Normalizar el vector propio para que sume 1
stable_stage_distribution <- stable_stage_distribution_raw/sum(stable_stage_distribution_raw)
stable_stage_distribution_df <- data.frame(Stage = factor(stage_names,
    levels = stage_names), Proportion = stable_stage_distribution)

# --- Calcular el Tiempo de Convergencia para cada Etapa
# --- Definir una tolerancia para la convergencia (por
# ejemplo, 1% de la proporción de SSD)
tolerance <- 0.01

# Crear un data frame para almacenar los tiempos de
# convergencia
convergence_times_df <- data.frame(Stage = character(), Time = numeric())

# Bucle a través de cada etapa para encontrar el primer
# paso de tiempo donde la proporción está dentro de la
# tolerancia de la SSD
for (i in 1:length(stage_names)) {
    stage_name <- stage_names[i]
    ssd_proportion <- stable_stage_distribution_df[stable_stage_distribution_df$Stage ==
        stage_name, "Proportion"]

    # Filtrar los datos para la etapa actual
    stage_data <- all_data_df[all_data_df$Stage == stage_name,
        ]

    # Encontrar la primera fila donde la proporción está
    # dentro de la banda de tolerancia
    convergence_time <- stage_data$Time[which(abs(stage_data$Proportion -
        ssd_proportion) <= tolerance)[1]]

    if (!is.na(convergence_time)) {
        convergence_times_df <- rbind(convergence_times_df, data.frame(Stage = stage_name,
            Time = convergence_time))
    }
}

# La función `factor` es necesaria para garantizar que los
# nombres de las etapas en `convergence_times_df` se
# muestren en el orden correcto.
convergence_times_df$Stage <- factor(convergence_times_df$Stage,
    levels = stage_names)

subexpr <- bquote("El crecimiento anual de la población es " *
    lambda == .(round(dominant_eigenvalue, 4)))

# --- Crear el Trazado Usando ggplot2 ---
population_plot <- ggplot(all_data_df, aes(x = Time, y = Proportion,
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable color
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable =
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable Stage))
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable +
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable geom_line(linewidth
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable =
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable 1.2)
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable +
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable #
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable Añadir
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable líneas
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable horizontales
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable para
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable la
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable distribución
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable de
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable etapa
    color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable estable
geom_hline(data = stable_stage_distribution_df, aes(yintercept = Proportion,
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia color
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia =
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia Stage),
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia linetype
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia =
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia "dashed",
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia linewidth
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia =
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia 0.8)
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia +
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia #
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia Añadir
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia líneas
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia verticales
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia para
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia el
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia tiempo
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia de
    color = Stage), linetype = "dashed", linewidth = 0.8) + # Añadir líneas verticales para el tiempo de convergencia convergencia
geom_vline(data = convergence_times_df, aes(xintercept = Time,
    color = Stage), linetype = "dotted", linewidth = 1) + labs(title = "Convergencia a la distribución estable ",
    subtitle = subexpr, x = "Paso de Tiempo", y = "Proporción de la Población",
    color = "Etapa de Vida") + rlt_style_colour() + theme_minimal(base_size = 12) +
    theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        plot.subtitle = element_text(hjust = 0.5), axis.title = element_text(face = "bold")) +
    xlim(0, max(all_data_df$Time))

# Imprimir el trazado final
print(population_plot)
Error in parse(text = input): <text>:122:18: unexpected ')'
121:     color = Stage)) + geom_line(linewidth = 1.2) + # Añadir líneas horizontales para la distribución de etapa estable color
122:     color = Stage)
                      ^

Estas propiedades estructurales permiten comprender el significado biológico de la tasa de crecimiento poblacional introducida en el capítulo sobre crecimiento poblacional.

Caswell H. 2001. Matrix Population Models: Construction, analysis, and interpretation. Sunderland, Massachusetts, USA: Sinauer Associates.
Crone EE, Menges ES, Ellis MM, Bell T, Bierzychudek P, Ehrlén J, Kaye TN, Knight TM, Lesica P, Morris WF, others. 2011. How do plant ecologists use matrix population models? Ecology Letters 14:1-8.
Jiang S, Jaggi H, Zuo W, Oli MK, Gaillard J-M, Tuljapurkar S. 2020. Life-history dynamics: damping time, demographic dispersion and generation time. bioRxiv:2020-12.
Mangalam M, Kelty-Stephen DG. 2022. Ergodic descriptors of non-ergodic stochastic processes. Journal of the Royal Society Interface 19:20220095.
Stott I, Townley S, Hodgson DJ. 2011. A framework for studying transient dynamics of population projection matrix models. Ecology Letters 14:959-970.
Tremblay R, Raventos J, Ackerman J. 2015. When stable-stage equilibrium is unlikely: integrating transient population dynamics improves asymptotic methods. Annals of Botany 116:381-390. DOI: 10.1093/aob/mcv031.
Williams JL, Ellis MM, Bricker MC, Brodie JF, Parsons EW. 2011. Distance to stable stage distribution in plant populations and implications for near-term population projections. Journal of Ecology 99:1171-1178.