Diplomado: MANEJO DE ECOSISTEMAS MARINOS COSTEROS DEL CARIBE
Programa: Biología — Universidad de La Guajira
Facultad: Ciencias Básicas y Aplicadas
Docente: Cristian Granados-Martínez PhD.


1 Introducción

1.1 ¿Qué es una curva de rango-abundancia de Whittaker?

Las curvas de rango-abundancia de Whittaker (RACs) ordenan las especies de una comunidad desde la más abundante (rango 1) hasta la menos abundante, graficando su abundancia relativa en escala logarítmica frente al rango.

Este tipo de gráfico, propuesto por Whittaker (1965), permite visualizar de manera simultánea tres propiedades clave de una comunidad:

Propiedad Lo que se lee en la curva
Riqueza Longitud de la curva — más especies = curva más larga
Dominancia Altura del primer punto — especies muy abundantes elevan el inicio
Equitabilidad Pendiente — curva pronunciada = alta dominancia; curva suave = comunidad más equitativa

1.2 Ventajas frente a los índices numéricos

A diferencia de un solo número como H’ o J’, la curva de Whittaker muestra la estructura completa de la comunidad: cuántas especies son dominantes, cuántas son comunes y cuántas son raras. Dos comunidades pueden tener el mismo valor de Shannon y estructuras completamente distintas.

1.3 Aplicación en ecosistemas marinos costeros

En arrecifes de coral, pastos marinos y manglares del Caribe colombiano, las RACs son especialmente útiles para:

  • Comparar la estructura de dominancia entre sitios protegidos y no protegidos
  • Evaluar cambios en la comunidad entre temporadas (lluvias vs. seca)
  • Detectar el efecto de perturbaciones como el blanqueamiento o la pesca sobre la distribución de abundancias

2 Instalación y Carga de Paquetes

# Ejecuten este bloque UNA SOLA VEZ
install.packages(c("vegan", "tidyverse", "ggrepel", "cowplot", "gridExtra"))
# Ejecuten al inicio de cada sesión
library(vegan)
library(tidyverse)
library(ggrepel)
library(cowplot)
library(gridExtra)
library(knitr)

cat("Paquetes cargados correctamente.\n")
## Paquetes cargados correctamente.
cat("vegan:", as.character(packageVersion("vegan")), "\n")
## vegan: 2.6.10

3 Funciones Auxiliares

Definimos tres funciones reutilizables que usaremos a lo largo de toda la guía:

# ── Función 1: Calcular tabla de rango-abundancia ────────────────────────────
# Convierte un vector de conteos en una tabla ordenada por rango
rank_abundance <- function(x, nombres = NULL) {
  idx  <- x > 0
  x    <- x[idx]
  if (!is.null(nombres)) nombres <- nombres[idx]
  ord  <- order(x, decreasing = TRUE)
  x    <- x[ord]
  if (!is.null(nombres)) nombres <- nombres[ord]
  out  <- tibble(
    rango  = seq_along(x),
    abund  = as.numeric(x),
    prop   = abund / sum(abund)
  )
  if (!is.null(nombres)) out$especie <- nombres
  out
}

# ── Función 2: Graficar RAC con ggplot2 ──────────────────────────────────────
plot_rac <- function(df, titulo = NULL, color = "#1F6E8C") {
  ggplot(df, aes(x = rango, y = prop)) +
    geom_line(color = color, linewidth = 1.2) +
    geom_point(color = color, size = 3, alpha = 0.85) +
    scale_y_continuous(trans = "log10",
                       labels = scales::label_number(accuracy = 0.001)) +
    labs(
      title = titulo,
      x     = "Rango (1 = especie más abundante)",
      y     = "Abundancia relativa (log₁₀)"
    ) +
    theme_classic(base_size = 12) +
    theme(plot.title = element_text(face = "bold", hjust = 0.5))
}

# ── Función 3: Calcular pendiente de la RAC ───────────────────────────────────
# Pendiente más negativa = mayor dominancia / menor equitabilidad
pendiente_rac <- function(df) {
  fit <- lm(log10(prop) ~ rango, data = df)
  round(unname(coef(fit)[2]), 4)
}

cat("Funciones definidas correctamente.\n")
## Funciones definidas correctamente.

💡 Cómo interpretar la pendiente: se calcula como la regresión de log₁₀(abundancia relativa) ~ rango. Una pendiente de 0 indica perfecta equitabilidad; valores más negativos indican mayor dominancia de pocas especies.


4 Datos: Peces Arrecifales del Caribe Colombiano

4.1 Descripción

Trabajamos con censos visuales de peces arrecifales registrados en cuatro sitios del Caribe colombiano, dos dentro de zonas protegidas (Parque Tayrona) y dos en zonas no protegidas (Cabo de la Vela). Los datos corresponden a conteos por transecto de 25 m².

set.seed(2026)

# ── Especies registradas ──────────────────────────────────────────────────────
especies <- c(
  "Acanthurus bahianus",    "Sparisoma viride",
  "Haemulon sciurus",       "Epinephelus guttatus",
  "Stegastes partitus",     "Lutjanus apodus",
  "Cephalopholis cruentata","Holocanthus tricolor",
  "Pomacanthus paru",       "Chaetodon capistratus",
  "Bodianus rufus",         "Thalassoma bifasciatum",
  "Scarus iserti",          "Abudefduf saxatilis",
  "Gramma loreto"
)

# ── Matriz de abundancias (filas = sitios, columnas = especies) ───────────────
abundancias <- matrix(
  c(# Tayrona_1 — zona protegida, alta cobertura de coral
    22, 18, 15, 8, 25, 10, 6, 5, 4, 14, 9, 20, 12, 30, 3,
    # Tayrona_2 — zona protegida
    19, 20, 12, 6, 22, 8,  5, 4, 3, 12, 7, 18, 10, 28, 2,
    # Vela_1 — zona no protegida, baja cobertura coral
    8,  5,  3,  1, 10, 2,  1, 0, 0,  4, 2,  7,  3, 45, 0,
    # Vela_2 — zona no protegida
    6,  4,  2,  1,  8, 1,  1, 0, 0,  3, 1,  5,  2, 48, 0),
  nrow  = 4,
  byrow = TRUE,
  dimnames = list(
    c("Tayrona_1", "Tayrona_2", "Vela_1", "Vela_2"),
    especies
  )
)

kable(abundancias,
      caption = "Abundancia de peces arrecifales por sitio (ind./transecto de 25 m²)",
      align   = "c")
Abundancia de peces arrecifales por sitio (ind./transecto de 25 m²)
Acanthurus bahianus Sparisoma viride Haemulon sciurus Epinephelus guttatus Stegastes partitus Lutjanus apodus Cephalopholis cruentata Holocanthus tricolor Pomacanthus paru Chaetodon capistratus Bodianus rufus Thalassoma bifasciatum Scarus iserti Abudefduf saxatilis Gramma loreto
Tayrona_1 22 18 15 8 25 10 6 5 4 14 9 20 12 30 3
Tayrona_2 19 20 12 6 22 8 5 4 3 12 7 18 10 28 2
Vela_1 8 5 3 1 10 2 1 0 0 4 2 7 3 45 0
Vela_2 6 4 2 1 8 1 1 0 0 3 1 5 2 48 0

5 RAC Básica en un Solo Sitio

Comenzamos construyendo la curva para Tayrona_1, el sitio de mayor cobertura de coral.

# Extraer abundancias del sitio 1
com_tayrona1 <- as.numeric(abundancias["Tayrona_1", ])

# Construir tabla de rango-abundancia
rac_t1 <- rank_abundance(com_tayrona1, nombres = especies)

# Mostrar los primeros rangos
kable(head(rac_t1, 8),
      col.names = c("Rango", "Abundancia", "Prop. relativa", "Especie"),
      caption   = "Primeros 8 rangos — Tayrona_1",
      digits    = 4)
Primeros 8 rangos — Tayrona_1
Rango Abundancia Prop. relativa Especie
1 30 0.1493 Abudefduf saxatilis
2 25 0.1244 Stegastes partitus
3 22 0.1095 Acanthurus bahianus
4 20 0.0995 Thalassoma bifasciatum
5 18 0.0896 Sparisoma viride
6 15 0.0746 Haemulon sciurus
7 14 0.0697 Chaetodon capistratus
8 12 0.0597 Scarus iserti
plot_rac(rac_t1,
         titulo = "RAC — Tayrona_1 (zona protegida)",
         color  = "#1F6E8C")
RAC del sitio Tayrona_1. La pendiente suave indica alta equitabilidad.

RAC del sitio Tayrona_1. La pendiente suave indica alta equitabilidad.

cat("Pendiente de la RAC (Tayrona_1):", pendiente_rac(rac_t1), "\n")
## Pendiente de la RAC (Tayrona_1): -0.0669
cat("Interpretación: pendientes menos negativas indican mayor equitabilidad.\n")
## Interpretación: pendientes menos negativas indican mayor equitabilidad.

6 Comparación entre dos Sitios con Esfuerzo Estandarizado

Antes de comparar dos comunidades es fundamental igualar el esfuerzo de muestreo. Si un sitio tiene más individuos, naturalmente detectará más especies. La rarefacción resuelve esto submuestreando al tamaño mínimo.

com_vela1 <- as.numeric(abundancias["Vela_1", ])

n1    <- sum(com_tayrona1)
n2    <- sum(com_vela1)
n_min <- min(n1, n2)

cat("Total individuos Tayrona_1:", n1, "\n")
## Total individuos Tayrona_1: 201
cat("Total individuos Vela_1:   ", n2, "\n")
## Total individuos Vela_1:    91
cat("Estandarizando a:          ", n_min, "individuos\n\n")
## Estandarizando a:           91 individuos
# Rarefacción
com_t1_std <- as.numeric(rrarefy(matrix(com_tayrona1, nrow = 1), sample = n_min))
com_v1_std <- as.numeric(rrarefy(matrix(com_vela1,    nrow = 1), sample = n_min))

rac_t1_std <- rank_abundance(com_t1_std) |> mutate(sitio = "Tayrona_1 (protegido)")
rac_v1_std <- rank_abundance(com_v1_std) |> mutate(sitio = "Vela_1 (no protegido)")
rac_comp   <- bind_rows(rac_t1_std, rac_v1_std)

ggplot(rac_comp, aes(x = rango, y = prop, color = sitio, group = sitio)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3, alpha = 0.85) +
  scale_y_continuous(trans = "log10",
                     labels = scales::label_number(accuracy = 0.001)) +
  scale_color_manual(values = c("Tayrona_1 (protegido)"    = "#1F6E8C",
                                "Vela_1 (no protegido)"    = "#C0415A")) +
  labs(
    title    = "Comparación RAC — Zona Protegida vs. No Protegida",
    subtitle = paste0("Estandarizado a ", n_min, " individuos por rarefacción"),
    x        = "Rango (1 = especie más abundante)",
    y        = "Abundancia relativa (log₁₀)",
    color    = "Sitio"
  ) +
  theme_classic(base_size = 13) +
  theme(legend.position = "bottom")
Comparación de RACs entre zona protegida y no protegida, estandarizadas por rarefacción.

Comparación de RACs entre zona protegida y no protegida, estandarizadas por rarefacción.

data.frame(
  Sitio     = c("Tayrona_1 (protegido)", "Vela_1 (no protegido)"),
  N_total   = c(n1, n2),
  N_std     = c(n_min, n_min),
  Riqueza   = c(sum(com_t1_std > 0), sum(com_v1_std > 0)),
  Pendiente = c(pendiente_rac(rac_t1_std), pendiente_rac(rac_v1_std))
) |>
  kable(col.names = c("Sitio", "N original", "N estandarizado",
                      "Riqueza (std)", "Pendiente"),
        caption   = "Comparación de RACs estandarizadas",
        align     = "c")
Comparación de RACs estandarizadas
Sitio N original N estandarizado Riqueza (std) Pendiente
Tayrona_1 (protegido) 201 91 15 -0.0689
Vela_1 (no protegido) 91 91 12 -0.1221

Interpretación: la curva más larga indica mayor riqueza; la pendiente menos negativa indica mayor equitabilidad (abundancias más uniformes entre especies). Una curva muy inclinada revela alta dominancia de pocas especies.


7 Efecto de la Equitabilidad — Ejemplo Conceptual

Para entender qué forma toma la curva en casos extremos, construimos dos comunidades sintéticas con igual riqueza pero diferente equitabilidad.

S <- 15

# Comunidad equitativa: todos los individuos repartidos por igual
com_equit <- rep(20, S)

# Comunidad dominante: una especie acapara la mayoría
com_domin <- c(200, rep(3, S - 1))

rac_eq <- rank_abundance(com_equit) |> mutate(tipo = "Comunidad equitativa")
rac_do <- rank_abundance(com_domin) |> mutate(tipo = "Comunidad dominante")

bind_rows(rac_eq, rac_do) |>
  ggplot(aes(x = rango, y = prop, color = tipo, group = tipo)) +
  geom_line(linewidth = 1.3) +
  geom_point(size = 3) +
  scale_y_continuous(trans = "log10",
                     labels = scales::label_number(accuracy = 0.001)) +
  scale_color_manual(values = c("Comunidad equitativa" = "#2E86AB",
                                "Comunidad dominante"  = "#E84855")) +
  labs(
    title    = "Misma Riqueza (S = 15), Distinta Equitabilidad",
    subtitle = "Curva plana = equitativa | Curva inclinada = dominante",
    x        = "Rango",
    y        = "Abundancia relativa (log₁₀)",
    color    = NULL
  ) +
  theme_classic(base_size = 13) +
  theme(legend.position = "bottom")
Efecto de la equitabilidad en la forma de la RAC. Misma riqueza, muy diferente estructura.

Efecto de la equitabilidad en la forma de la RAC. Misma riqueza, muy diferente estructura.

data.frame(
  Tipo      = c("Comunidad equitativa", "Comunidad dominante"),
  Pendiente = c(pendiente_rac(rac_eq), pendiente_rac(rac_do))
) |>
  kable(col.names = c("Tipo de comunidad", "Pendiente"),
        caption   = "Pendientes de las RACs conceptuales",
        align     = "c")
Pendientes de las RACs conceptuales
Tipo de comunidad Pendiente
Comunidad equitativa 0.0000
Comunidad dominante -0.0456

8 Comparación de los Cuatro Sitios

Ahora construimos y comparamos las RACs de los cuatro sitios, etiquetando cada especie para facilitar la interpretación ecológica.

# Construir RACs para los 4 sitios con nombres de especies
sitios_lista <- c("Tayrona_1", "Tayrona_2", "Vela_1", "Vela_2")
zonas        <- c("Protegida", "Protegida", "No protegida", "No protegida")
colores_zona <- c("Protegida"    = "#1F6E8C",
                  "No protegida" = "#C0415A")

rac_todos <- purrr::map2_dfr(sitios_lista, zonas, function(s, z) {
  ab  <- as.numeric(abundancias[s, ])
  idx <- ab > 0
  ab_f <- ab[idx]; sp_f <- especies[idx]
  ord  <- order(ab_f, decreasing = TRUE)
  ab_f <- ab_f[ord]; sp_f <- sp_f[ord]
  tibble(
    sitio     = s,
    zona      = z,
    rango     = seq_along(ab_f),
    abund     = ab_f,
    prop      = ab_f / sum(ab_f),
    especie   = sp_f,
    abrev     = sapply(strsplit(sp_f, " "), function(x)
                  paste0(substr(x[1], 1, 3), ". ", substr(x[2], 1, 4)))
  )
})
ggplot(rac_todos, aes(x = rango, y = prop,
                      color = zona, group = sitio)) +
  geom_line(linewidth = 1.1, alpha = 0.85) +
  geom_point(size = 2.8) +
  geom_text_repel(
    aes(label = abrev),
    size          = 3,
    fontface      = "italic",
    point.padding = 0.3,
    box.padding   = 0.5,
    max.overlaps  = 20,
    show.legend   = FALSE
  ) +
  scale_y_continuous(trans  = "log10",
                     labels = scales::label_number(accuracy = 0.001)) +
  scale_color_manual(values = colores_zona) +
  facet_wrap(~ sitio, ncol = 2) +
  labs(
    title    = "Curvas de Rango-Abundancia — Peces Arrecifales del Caribe Colombiano",
    subtitle = "Cuatro sitios | Ejes Y en escala log₁₀",
    x        = "Rango (1 = especie más abundante)",
    y        = "Abundancia relativa (log₁₀)",
    color    = "Zona"
  ) +
  theme_bw(base_size = 12) +
  theme(
    legend.position  = "bottom",
    strip.background = element_rect(fill = "#2C3E50"),
    strip.text       = element_text(color = "white", face = "bold")
  )
Curvas de rango-abundancia de Whittaker para los cuatro sitios de arrecife. Las etiquetas muestran los géneros de peces en cada rango.

Curvas de rango-abundancia de Whittaker para los cuatro sitios de arrecife. Las etiquetas muestran los géneros de peces en cada rango.

# Tabla resumen de riqueza, equitabilidad y pendiente
resumen_rac <- rac_todos |>
  group_by(sitio, zona) |>
  summarise(
    Riqueza   = n(),
    N_total   = sum(abund),
    Prop_dom  = paste0(round(max(prop) * 100, 1), " %"),
    Sp_dom    = especie[which.max(prop)],
    Pendiente = pendiente_rac(pick(rango, prop)),
    .groups   = "drop"
  )

kable(resumen_rac,
      col.names = c("Sitio", "Zona", "Riqueza (S)", "N total",
                    "% especie dominante", "Especie dominante", "Pendiente"),
      caption   = "Resumen de RACs por sitio — peces arrecifales",
      align     = "c")
Resumen de RACs por sitio — peces arrecifales
Sitio Zona Riqueza (S) N total % especie dominante Especie dominante Pendiente
Tayrona_1 Protegida 15 201 14.9 % Abudefduf saxatilis -0.0669
Tayrona_2 Protegida 15 176 15.9 % Abudefduf saxatilis -0.0754
Vela_1 No protegida 12 91 49.5 % Abudefduf saxatilis -0.1221
Vela_2 No protegida 12 82 58.5 % Abudefduf saxatilis -0.1281

9 Cambio Temporal en la Estructura de la Comunidad

Las RACs también permiten visualizar cómo cambia la estructura de una comunidad entre momentos distintos (p. ej., antes y después de un evento de blanqueamiento, o entre estaciones climáticas).

set.seed(42)

antes   <- com_tayrona1

# Simulamos blanqueamiento: especie dominante pierde 60% y varias raras desaparecen
despues             <- antes
despues[which.max(despues)] <- round(despues[which.max(despues)] * 0.4)
raras               <- which(despues > 0 & despues <= 3)
despues[raras]      <- 0

rac_antes <- rank_abundance(antes,   nombres = especies) |> mutate(momento = "Antes del blanqueamiento")
rac_desp  <- rank_abundance(despues, nombres = especies) |> mutate(momento = "Después del blanqueamiento")

bind_rows(rac_antes, rac_desp) |>
  ggplot(aes(x = rango, y = prop, color = momento, group = momento)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3) +
  scale_y_continuous(trans  = "log10",
                     labels = scales::label_number(accuracy = 0.001)) +
  scale_color_manual(values = c("Antes del blanqueamiento"   = "#2E86AB",
                                "Después del blanqueamiento" = "#E84855")) +
  labs(
    title    = "Cambio Temporal en la RAC — Tayrona_1",
    subtitle = "Simulación del efecto de un evento de blanqueamiento",
    x        = "Rango",
    y        = "Abundancia relativa (log₁₀)",
    color    = NULL
  ) +
  theme_classic(base_size = 13) +
  theme(legend.position = "bottom")
Simulación de cambio en la RAC antes y después de un evento de blanqueamiento en Tayrona_1.

Simulación de cambio en la RAC antes y después de un evento de blanqueamiento en Tayrona_1.

data.frame(
  Momento   = c("Antes", "Después"),
  Riqueza   = c(sum(antes > 0), sum(despues > 0)),
  N_total   = c(sum(antes), sum(despues)),
  Pendiente = c(pendiente_rac(rac_antes), pendiente_rac(rac_desp))
) |>
  kable(col.names = c("Momento", "Riqueza (S)", "N total", "Pendiente"),
        caption   = "Cambio en la estructura de la comunidad tras el blanqueamiento",
        align     = "c")
Cambio en la estructura de la comunidad tras el blanqueamiento
Momento Riqueza (S) N total Pendiente
Antes 15 201 -0.0669
Después 14 180 -0.0575

10 Ajuste de Modelos SAD

El ajuste de distribuciones de abundancia de especies (SAD) complementa la lectura visual de las RACs. La función radfit() de vegan ajusta varios modelos clásicos y calcula su AIC para comparación.

fit <- radfit(com_tayrona1)
print(fit)
## 
## RAD models, family poisson 
## No. of species 15, total abundance 201
## 
##            par1     par2        par3        Deviance AIC      BIC     
## Null                                        17.58534 81.33635 81.33635
## Preemption  0.14338                          3.35302 69.10402 69.81207
## Lognormal   2.4205   0.62213                 2.64869 70.39970 71.81580
## Zipf        0.18784 -0.62663                11.99415 79.74515 81.16125
## Mandelbrot    Inf   -1.2247e+05  8.5103e+05  0.92911 70.68012 72.80427
plot(fit, main = "Ajuste de Modelos SAD — Tayrona_1 (peces arrecifales)")
Gráfico diagnóstico de los modelos SAD ajustados.

Gráfico diagnóstico de los modelos SAD ajustados.

💡 ¿Qué modelo elegir? El menor AIC no siempre es el mejor criterio ecológico. Si varios modelos tienen AIC similares (diferencia < 2), conviene elegir el más parsimonioso o el que mejor se ajusta a la biología del sistema.


11 Tabla Comparativa Final

tabla_final <- resumen_rac |>
  mutate(
    Shannon   = apply(abundancias[sitios_lista, ], 1,
                      function(x) round(diversity(x, index = "shannon"), 3)),
    Pielou    = round(Shannon / log(Riqueza), 3)
  ) |>
  select(sitio, zona, Riqueza, N_total, Pendiente, Shannon, Pielou)

kable(tabla_final,
      col.names = c("Sitio", "Zona", "Riqueza (S)", "N total",
                    "Pendiente RAC", "Shannon (H')", "Pielou (J')"),
      caption   = "Comparación integral de diversidad alfa — índices clásicos + RAC",
      align     = "c",
      digits    = 3)
Comparación integral de diversidad alfa — índices clásicos + RAC
Sitio Zona Riqueza (S) N total Pendiente RAC Shannon (H’) Pielou (J’)
Tayrona_1 Protegida 15 201 -0.067 2.533 0.935
Tayrona_2 Protegida 15 176 -0.075 2.494 0.921
Vela_1 No protegida 12 91 -0.122 1.791 0.721
Vela_2 No protegida 12 82 -0.128 1.567 0.631

💡 Clave de lectura: los índices numéricos (H’, J’) resumen la diversidad en un solo número; la pendiente de la RAC complementa esta información mostrando la forma de la distribución de abundancias. Úsenlos siempre en conjunto.


12 Recomendaciones Prácticas

  1. Estandaricen siempre por esfuerzo antes de comparar RACs entre sitios. Usen rarefacción (rrarefy) o cobertura muestral equivalente.

  2. Reporten riqueza y equidad conjuntamente. Una RAC larga y plana es el escenario ideal: muchas especies con abundancias similares.

  3. Complementen con ajuste de SADs (radfit) y evalúen varios modelos; el AIC más bajo no siempre es el ecológicamente más relevante.

  4. En series temporales, analicen cambios en riqueza (longitud), equidad (pendiente) y reordenamiento de rangos para caracterizar la dinámica de la comunidad.

  5. En ecosistemas del Caribe, presten especial atención a las especies que pasan de rangos intermedios a dominantes, ya que pueden indicar perturbación (p. ej., dominio de Abudefduf en zonas con alta presión de pesca).


13 Ejercicios Prácticos

13.1 Ejercicio 1 — Lectura e interpretación

Observen la tabla de resumen (sección 6) y respondan:

a) ¿Cuál sitio tiene la pendiente menos negativa? ¿Qué implica esto sobre la equitabilidad de su comunidad?

b) ¿Qué especie domina en los sitios no protegidos? ¿Tiene sentido ecológico que esa especie sea la más abundante bajo presión de pesca? Justifiquen.

# Código de apoyo: consulten la tabla resumen
print(resumen_rac)

13.2 Ejercicio 2 — Comparación con rarefacción

Comparen los sitios Tayrona_2 y Vela_2 aplicando rarefacción. Construyan la RAC comparativa y calculen las pendientes.

# ── COMPLETEN: extraigan las abundancias de Tayrona_2 y Vela_2 ───────────────
com_t2 <- as.numeric(abundancias["SITIO_1", ])
com_v2 <- as.numeric(abundancias["SITIO_2", ])

# ── COMPLETEN: igualen al tamaño mínimo con rrarefy ──────────────────────────
n_min2    <- min(sum(com_t2), sum(com_v2))
com_t2_st <- as.numeric(rrarefy(matrix(com_t2, nrow = 1), sample = n_min2))
com_v2_st <- as.numeric(rrarefy(matrix(com_v2, nrow = 1), sample = n_min2))

# ── COMPLETEN: construyan las RACs y el gráfico comparativo ──────────────────
rac_t2 <- rank_abundance(VECTOR_1) |> mutate(sitio = "Tayrona_2")
rac_v2 <- rank_abundance(VECTOR_2) |> mutate(sitio = "Vela_2")

bind_rows(rac_t2, rac_v2) |>
  ggplot(aes(x = rango, y = prop, color = sitio, group = sitio)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3) +
  scale_y_continuous(trans = "log10") +
  scale_color_manual(values = c("Tayrona_2" = "#1F6E8C",
                                "Vela_2"    = "#C0415A")) +
  labs(title = "TITULO DEL GRAFICO",
       x = "Rango", y = "Abundancia relativa (log₁₀)", color = "Sitio") +
  theme_classic(base_size = 13) +
  theme(legend.position = "bottom")

# ── COMPLETEN: calculen las pendientes ───────────────────────────────────────
cat("Pendiente Tayrona_2:", pendiente_rac(rac_t2), "\n")
cat("Pendiente Vela_2:   ", pendiente_rac(rac_v2), "\n")

13.3 Ejercicio 3 — Su propia base de datos

Con los datos del taller grupal (macroinvertebrados de manglar — lluvias y seca), construyan una RAC para cada estación y comparen su pendiente con los índices de Shannon y Pielou ya calculados. ¿Coinciden las conclusiones?

# Datos del taller — manglar del Caribe colombiano
manglar <- matrix(
  c(161, 3, 44, 55, 0,  212, 4, 27, 48,
    357, 0, 0,  185, 2, 22,  0, 30, 767),
  nrow  = 2,
  byrow = TRUE,
  dimnames = list(
    c("Lluvias", "Seca"),
    c("Aratus_pisonii", "Callinectes_bocourti", "Cardisoma_guanhumi",
      "Goniopsis_cruentata", "Marisa_cornuarietis", "Minuca_vocator",
      "Polymesoda_arctata", "Pomacea_maculata", "Vitta_virginea")
  )
)
kable(manglar, caption = "Macroinvertebrados de manglar — datos del taller",
      align = "c")
Macroinvertebrados de manglar — datos del taller
Aratus_pisonii Callinectes_bocourti Cardisoma_guanhumi Goniopsis_cruentata Marisa_cornuarietis Minuca_vocator Polymesoda_arctata Pomacea_maculata Vitta_virginea
Lluvias 161 3 44 55 0 212 4 27 48
Seca 357 0 0 185 2 22 0 30 767
# ── COMPLETEN: construyan la RAC para cada estación y compárenlas ─────────────
com_lluv <- as.numeric(manglar["Lluvias", ])
com_seca <- as.numeric(manglar["Seca",    ])

rac_lluv <- rank_abundance(com_lluv,
                           nombres = colnames(manglar)) |>
  mutate(estacion = "Lluvias")

rac_seca <- rank_abundance(com_seca,
                           nombres = colnames(manglar)) |>
  mutate(estacion = "Seca")

# Gráfico comparativo
bind_rows(rac_lluv, rac_seca) |>
  ggplot(aes(x = rango, y = prop, color = estacion, group = estacion)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3) +
  geom_text_repel(aes(label = especie), size = 3, fontface = "italic",
                  show.legend = FALSE, max.overlaps = 15) +
  scale_y_continuous(trans = "log10") +
  scale_color_manual(values = c("Lluvias" = "#4E9BB9",
                                "Seca"    = "#E07B54")) +
  labs(title = "TITULO DEL GRAFICO",
       x = "Rango", y = "Abundancia relativa (log₁₀)", color = "Estación") +
  theme_classic(base_size = 13) +
  theme(legend.position = "bottom")

# Pendientes
cat("Pendiente Lluvias:", pendiente_rac(rac_lluv), "\n")
cat("Pendiente Seca:   ", pendiente_rac(rac_seca), "\n")

14 Próximos Contenidos

Esta es la Parte 5 de la guía. En la siguiente parte exploraremos:

  • Números de Hill como alternativa unificada a los índices clásicos
  • Curvas de interpolación y extrapolación con el paquete iNEXT
  • Perfiles de diversidad por orden q (q = 0, 1, 2)

15 Bibliografía

  • Whittaker, R. H. (1965). Dominance and diversity in land plant communities. Science, 147(3655), 250–260.
  • Avolio, M. L. et al. (2019). A comprehensive approach to analyzing community dynamics using rank abundance curves. Ecosphere, 10(10), e02881.
  • McGill, B. J. et al. (2007). Species abundance distributions: Moving beyond single prediction theories. Ecology Letters, 10(10), 995–1015.
  • Oksanen, J. et al. (2022). vegan: Community Ecology Package. R package version 2.6-4.

Recursos en línea:


Cristian Granados-Martínez PhD. — Programa de Biología, Universidad de La Guajira
Diplomado en Manejo de Ecosistemas Marinos Costeros del Caribe — 2026