1 Objetivo

En este documento se usan datos climaticos globales de linea base de WorldClim para construir mapas de aptitud climatica para cana de azucar. La evaluacion se hace con los rangos optimos indicados:

  • Temperatura media: 22.5 a 28 grados centigrados.
  • Precipitacion anual: 1500 a 3500 mm.
  • Precipitacion mensual: 125 a 290 mm.

Tambien se identifican paises con alto potencial, se extrae clima mensual en puntos del Valle del Cauca y se generan mapas globales de similaridad climatica usando distancia euclidiana.

2 Paquetes y rutas

paquetes <- c(
  "terra", "geodata", "sf", "dplyr", "tidyr", "ggplot2",
  "scales", "knitr"
)

faltantes <- paquetes[!vapply(paquetes, requireNamespace, logical(1), quietly = TRUE)]
if (length(faltantes) > 0) {
  install.packages(faltantes, dependencies = TRUE)
}

invisible(lapply(paquetes, library, character.only = TRUE))

dir_proyecto <- "C:/Users/Usuario/Documents/PROYECTOS GEO/ACTIVIDAD 2"
dir_caso <- file.path(dir_proyecto, "INFO CASO")
dir_datos <- file.path(dir_proyecto, "datos_clima")
dir_salida <- file.path(dir_proyecto, "salidas")

dir.create(dir_datos, showWarnings = FALSE, recursive = TRUE)
dir.create(dir_salida, showWarnings = FALSE, recursive = TRUE)

ruta_comuna <- file.path(dir_caso, "Comuna.shp")

3 Datos climaticos globales

La base climatica utilizada corresponde a WorldClim, con capas mensuales de temperatura media y precipitacion a resolucion espacial de 10 minutos de arco. A partir de estas capas se derivan la temperatura media anual, la precipitacion anual acumulada y el comportamiento mensual de la precipitacion.

resolucion_wc <- 10

terra::terraOptions(progress = 0)

tmedia <- geodata::worldclim_global(
  var = "tavg",
  res = resolucion_wc,
  path = dir_datos
)

prec <- geodata::worldclim_global(
  var = "prec",
  res = resolucion_wc,
  path = dir_datos
)

names(tmedia) <- sprintf("tmedia_%02d", 1:12)
names(prec) <- sprintf("prec_%02d", 1:12)

tmedia_anual <- mean(tmedia, na.rm = TRUE)
prec_anual <- sum(prec, na.rm = TRUE)

names(tmedia_anual) <- "temperatura_media_anual"
names(prec_anual) <- "precipitacion_anual"

paises <- geodata::world(path = dir_datos)
paises <- terra::project(paises, terra::crs(tmedia_anual))
mascara_tierra <- terra::rasterize(paises, tmedia_anual, field = 1, background = NA)

4 Funcion de aptitud climatica

La funcion siguiente asigna un valor entre 0 y 1. El valor es 1 dentro del rango optimo y disminuye hacia 0 por fuera del rango. Los limites absolutos se usan para evitar que un pixel apenas por fuera del rango optimo pase directamente a 0.

score_rango <- function(x, opt_min, opt_max, abs_min, abs_max) {
  score <- terra::ifel(
    x < abs_min | x > abs_max,
    0,
    terra::ifel(
      x >= opt_min & x <= opt_max,
      1,
      terra::ifel(
        x < opt_min,
        (x - abs_min) / (opt_min - abs_min),
        (abs_max - x) / (abs_max - opt_max)
      )
    )
  )
  terra::clamp(score, lower = 0, upper = 1, values = TRUE)
}

pal_aptitud <- hcl.colors(100, "YlGn", rev = FALSE)
pal_sim <- hcl.colors(100, "Viridis", rev = FALSE)

valor_global <- function(r, fun) {
  as.numeric(terra::global(r, fun, na.rm = TRUE)[1, 1])
}

percentil_global <- function(r, p) {
  as.numeric(terra::global(
    r,
    fun = function(x, ...) quantile(x, probs = p, na.rm = TRUE)
  )[1, 1])
}

area_condicion <- function(condicion, raster_base) {
  area_km2 <- terra::cellSize(raster_base, unit = "km")
  area_condicion_km2 <- area_km2 * condicion
  names(area_condicion_km2) <- "area_km2"
  area_por_pais <- terra::extract(
    area_condicion_km2,
    paises,
    fun = sum,
    na.rm = TRUE
  )
  sum(area_por_pais$area_km2, na.rm = TRUE)
}

resumen_raster <- function(r, nombre, umbral_alto = 0.75) {
  data.frame(
    mapa = nombre,
    minimo = valor_global(r, "min"),
    promedio = valor_global(r, "mean"),
    maximo = valor_global(r, "max"),
    p75 = percentil_global(r, 0.75),
    p90 = percentil_global(r, 0.90),
    area_alta_km2 = area_condicion(r >= umbral_alto, r)
  )
}

fmt_num <- function(x, digits = 1) {
  format(round(x, digits), big.mark = ",", scientific = FALSE)
}

5 Mapas globales de aptitud para cana de azucar

score_temp <- score_rango(
  tmedia_anual,
  opt_min = 22.5,
  opt_max = 28,
  abs_min = 15,
  abs_max = 35
)

score_prec_anual <- score_rango(
  prec_anual,
  opt_min = 1500,
  opt_max = 3500,
  abs_min = 750,
  abs_max = 4500
)

score_prec_mensual <- mean(
  score_rango(
    prec,
    opt_min = 125,
    opt_max = 290,
    abs_min = 50,
    abs_max = 400
  ),
  na.rm = TRUE
)

names(score_temp) <- "score_temperatura"
names(score_prec_anual) <- "score_precipitacion_anual"
names(score_prec_mensual) <- "score_precipitacion_mensual"

score_temp <- terra::mask(score_temp, mascara_tierra)
score_prec_anual <- terra::mask(score_prec_anual, mascara_tierra)
score_prec_mensual <- terra::mask(score_prec_mensual, mascara_tierra)

# Promedio geometrico: penaliza los sitios donde alguna condicion sea baja.
aptitud_cana <- (score_temp * score_prec_anual * score_prec_mensual)^(1 / 3)
names(aptitud_cana) <- "aptitud_climatica_cana"

aptitud_optima_binaria <- (
  tmedia_anual >= 22.5 & tmedia_anual <= 28 &
    prec_anual >= 1500 & prec_anual <= 3500 &
    app(prec >= 125 & prec <= 290, fun = all)
)
names(aptitud_optima_binaria) <- "cumple_rangos_optimos"
aptitud_optima_binaria <- terra::mask(aptitud_optima_binaria, mascara_tierra)

plot(score_temp, col = pal_aptitud, main = "Aptitud por temperatura media anual")

plot(score_prec_anual, col = pal_aptitud, main = "Aptitud por precipitacion anual")

plot(score_prec_mensual, col = pal_aptitud, main = "Aptitud por precipitacion mensual")

plot(aptitud_cana, col = pal_aptitud, main = "Aptitud climatica global para cana de azucar")

plot(
  aptitud_optima_binaria,
  col = c("gray85", "#238443"),
  main = "Zonas que cumplen todos los rangos optimos"
)

umbral_alto <- 0.75

resumen_aptitud <- bind_rows(
  resumen_raster(score_temp, "Temperatura media anual", umbral_alto),
  resumen_raster(score_prec_anual, "Precipitacion anual", umbral_alto),
  resumen_raster(score_prec_mensual, "Precipitacion mensual", umbral_alto),
  resumen_raster(aptitud_cana, "Aptitud climatica integrada", umbral_alto)
)

area_optima_km2 <- area_condicion(aptitud_optima_binaria == 1, aptitud_cana)
area_alta_global_km2 <- resumen_aptitud |>
  filter(mapa == "Aptitud climatica integrada") |>
  pull(area_alta_km2)

knitr::kable(
  resumen_aptitud,
  digits = 3,
  caption = "Resumen estadistico de los mapas globales de aptitud"
)
Resumen estadistico de los mapas globales de aptitud
mapa minimo promedio maximo p75 p90 area_alta_km2
Temperatura media anual 0 0.246 1 0.514 1.000 55935189
Precipitacion anual 0 0.139 1 0.000 0.785 25669060
Precipitacion mensual 0 0.149 1 0.211 0.544 9283994
Aptitud climatica integrada 0 0.103 1 0.000 0.599 18114540

El mapa integrado de aptitud climatica presenta un valor promedio global de 0.103 y alcanza valores maximos de 1. Bajo el umbral de aptitud alta definido en 0.75, el area potencial estimada es de 18,114,540 km2. Al aplicar simultaneamente todos los rangos optimos de temperatura, precipitacion anual y precipitacion mensual, el area estrictamente optima se reduce a 347,510 km2, lo que indica que la restriccion mensual de precipitacion es especialmente selectiva.

writeRaster(
  aptitud_cana,
  file.path(dir_salida, "aptitud_climatica_cana_worldclim.tif"),
  overwrite = TRUE
)

writeRaster(
  aptitud_optima_binaria,
  file.path(dir_salida, "aptitud_optima_binaria_cana_worldclim.tif"),
  overwrite = TRUE
)

6 Paises con areas de alto potencial

El potencial por pais se estima como la suma del area de las celdas con aptitud integrada alta, definida por valores iguales o superiores a 0.75.

paises <- terra::project(paises, terra::crs(aptitud_cana))

aptitud_alta <- aptitud_cana >= umbral_alto
area_celda_km2 <- terra::cellSize(aptitud_cana, unit = "km")
area_alta_km2 <- area_celda_km2 * aptitud_alta
names(area_alta_km2) <- "area_alta_km2"

area_paises <- terra::extract(
  area_alta_km2,
  paises,
  fun = sum,
  na.rm = TRUE
)

tabla_paises <- paises |>
  as.data.frame() |>
  mutate(ID = row_number()) |>
  left_join(area_paises, by = "ID") |>
  mutate(area_alta_km2 = replace_na(area_alta_km2, 0)) |>
  arrange(desc(area_alta_km2))

top_paises <- tabla_paises |>
  filter(area_alta_km2 > 0) |>
  slice_head(n = 3) |>
  select(NAME_0, area_alta_km2)

knitr::kable(
  top_paises,
  digits = 1,
  caption = "Tres paises con mayor area de aptitud alta para cana de azucar"
)
Tres paises con mayor area de aptitud alta para cana de azucar
NAME_0 area_alta_km2
Brazil 5885376
Democratic Republic of the Congo 1828893
Indonesia 1659881
paises_seleccionados <- top_paises$NAME_0
paises_top <- paises[paises$NAME_0 %in% paises_seleccionados, ]

resumen_paises_top <- data.frame(
  ID = seq_len(nrow(as.data.frame(paises_top))),
  NAME_0 = paises_top$NAME_0
) |>
  left_join(
    terra::extract(aptitud_cana, paises_top, fun = mean, na.rm = TRUE),
    by = "ID"
  ) |>
  rename(aptitud_media = aptitud_climatica_cana) |>
  left_join(
    terra::extract(aptitud_cana, paises_top, fun = max, na.rm = TRUE),
    by = "ID"
  ) |>
  rename(aptitud_maxima = aptitud_climatica_cana) |>
  left_join(top_paises, by = "NAME_0")

knitr::kable(
  resumen_paises_top |>
    select(NAME_0, area_alta_km2, aptitud_media, aptitud_maxima),
  digits = 3,
  caption = "Indicadores climaticos de los paises seleccionados"
)
Indicadores climaticos de los paises seleccionados
NAME_0 area_alta_km2 aptitud_media aptitud_maxima
Brazil 5885376 0.748 1
Democratic Republic of the Congo 1828893 0.844 1
Indonesia 1659881 0.898 1
aptitud_top_paises <- terra::mask(
  terra::crop(aptitud_cana, paises_top),
  paises_top
)

plot(
  aptitud_top_paises,
  col = pal_aptitud,
  main = "Aptitud climatica en paises con mayor potencial"
)
plot(paises_top, add = TRUE, border = "gray20", lwd = 0.8)

Los tres paises con mayor area de aptitud alta son Brazil, Democratic Republic of the Congo, Indonesia. Brasil concentra la mayor extension potencial, con 5,885,376 km2, seguido por Democratic Republic of the Congo y Indonesia. En estos paises, los valores maximos de aptitud se acercan a 1, lo que confirma la presencia de zonas climaticamente muy favorables, aunque la aptitud media nacional es menor porque incluye regiones con limitaciones termicas o pluviometricas.

for (pais in paises_seleccionados) {
  pais_i <- paises[paises$NAME_0 == pais, ]
  apt_i <- terra::mask(terra::crop(aptitud_cana, pais_i), pais_i)
  plot(
    apt_i,
    col = pal_aptitud,
    main = paste("Aptitud climatica para cana de azucar -", pais)
  )
  plot(pais_i, add = TRUE, border = "gray20", lwd = 0.8)
}

7 Puntos en el Valle del Cauca y extraccion de clima

Los puntos de referencia se ubican en el corredor agricola del Valle del Cauca, usando coordenadas en grados decimales para Palmira, El Cerrito y Buga.

puntos_valle <- data.frame(
  sitio = c("Palmira", "El Cerrito", "Buga"),
  lon = c(-76.3036, -76.3143, -76.2978),
  lat = c(3.5394, 3.6850, 3.9009)
)

puntos_vect <- terra::vect(
  puntos_valle,
  geom = c("lon", "lat"),
  crs = "EPSG:4326"
)

departamentos_col <- geodata::gadm(
  country = "COL",
  level = 1,
  path = dir_datos
)
valle_cauca <- departamentos_col[departamentos_col$NAME_1 == "Valle del Cauca", ]
valle_cauca <- terra::project(valle_cauca, "EPSG:4326")

plot(
  valle_cauca,
  col = "gray92",
  border = "gray35",
  main = "Puntos de referencia en el Valle del Cauca"
)

if (file.exists(ruta_comuna)) {
  comuna <- terra::vect(ruta_comuna)
  comuna <- terra::project(comuna, "EPSG:4326")
  plot(comuna, add = TRUE, border = "gray65", lwd = 0.6)
}

points(puntos_vect, col = "#d95f02", pch = 19, cex = 1.2)
coords_puntos <- terra::crds(puntos_vect)
text(coords_puntos[, 1], coords_puntos[, 2], labels = puntos_valle$sitio, pos = 4, cex = 0.85)

clima_stack <- c(tmedia, prec)
clima_puntos <- terra::extract(clima_stack, puntos_vect) |>
  select(-ID) |>
  bind_cols(puntos_valle)

temp_puntos <- clima_puntos |>
  select(sitio, starts_with("tmedia_")) |>
  pivot_longer(
    cols = starts_with("tmedia_"),
    names_to = "mes",
    values_to = "temperatura"
  ) |>
  mutate(mes = as.integer(sub("tmedia_", "", mes)))

prec_puntos <- clima_puntos |>
  select(sitio, starts_with("prec_")) |>
  pivot_longer(
    cols = starts_with("prec_"),
    names_to = "mes",
    values_to = "precipitacion"
  ) |>
  mutate(mes = as.integer(sub("prec_", "", mes)))

serie_puntos <- left_join(temp_puntos, prec_puntos, by = c("sitio", "mes"))

knitr::kable(
  serie_puntos,
  digits = 1,
  caption = "Clima mensual extraido para los puntos del Valle del Cauca"
)
Clima mensual extraido para los puntos del Valle del Cauca
sitio mes temperatura precipitacion
Palmira 1 22.5 92
Palmira 2 22.6 102
Palmira 3 22.7 132
Palmira 4 22.4 172
Palmira 5 22.4 146
Palmira 6 22.3 112
Palmira 7 22.6 61
Palmira 8 22.7 73
Palmira 9 22.6 105
Palmira 10 22.0 195
Palmira 11 21.9 173
Palmira 12 22.1 121
El Cerrito 1 21.0 95
El Cerrito 2 21.1 97
El Cerrito 3 21.3 130
El Cerrito 4 21.0 175
El Cerrito 5 20.9 152
El Cerrito 6 20.8 110
El Cerrito 7 21.1 63
El Cerrito 8 21.1 79
El Cerrito 9 21.0 111
El Cerrito 10 20.5 202
El Cerrito 11 20.4 171
El Cerrito 12 20.7 123
Buga 1 21.8 91
Buga 2 22.0 101
Buga 3 22.1 132
Buga 4 21.8 184
Buga 5 21.7 167
Buga 6 21.6 133
Buga 7 22.0 77
Buga 8 21.9 95
Buga 9 21.8 118
Buga 10 21.2 208
Buga 11 21.1 174
Buga 12 21.5 120
resumen_clima_puntos <- serie_puntos |>
  group_by(sitio) |>
  summarise(
    temp_media = mean(temperatura, na.rm = TRUE),
    temp_min = min(temperatura, na.rm = TRUE),
    temp_max = max(temperatura, na.rm = TRUE),
    prec_anual = sum(precipitacion, na.rm = TRUE),
    prec_min_mensual = min(precipitacion, na.rm = TRUE),
    prec_max_mensual = max(precipitacion, na.rm = TRUE),
    meses_temp_optima = sum(temperatura >= 22.5 & temperatura <= 28),
    meses_prec_optima = sum(precipitacion >= 125 & precipitacion <= 290),
    .groups = "drop"
  )

knitr::kable(
  resumen_clima_puntos,
  digits = 1,
  caption = "Resumen climatico anual de los puntos de referencia"
)
Resumen climatico anual de los puntos de referencia
sitio temp_media temp_min temp_max prec_anual prec_min_mensual prec_max_mensual meses_temp_optima meses_prec_optima
Buga 21.7 21.1 22.1 1600 77 208 0 6
El Cerrito 20.9 20.4 21.3 1508 63 202 0 5
Palmira 22.4 21.9 22.7 1484 61 195 6 5

Los puntos evaluados presentan precipitaciones anuales entre 1,484 y 1,600 mm. Palmira queda ligeramente por debajo del limite anual optimo de 1500 mm, mientras que El Cerrito y Buga se ubican en el tramo inferior del rango optimo. La temperatura media anual varia entre 20.9 y 22.4 grados C; Palmira es el punto mas cercano al limite inferior optimo de 22.5 grados C. La precipitacion mensual muestra un comportamiento bimodal, con maximos hacia abril y octubre, y minimos relativos en julio y agosto.

ggplot(serie_puntos, aes(x = mes, y = temperatura, color = sitio)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  scale_x_continuous(breaks = 1:12) +
  scale_color_brewer(palette = "Dark2") +
  labs(
    title = "Serie mensual de temperatura media",
    x = "Mes",
    y = "Temperatura media (grados C)",
    color = "Sitio"
  ) +
  theme_minimal(base_size = 12)

ggplot(serie_puntos, aes(x = mes, y = precipitacion, fill = sitio)) +
  geom_col(position = "dodge", width = 0.75) +
  scale_x_continuous(breaks = 1:12) +
  scale_fill_brewer(palette = "Dark2") +
  labs(
    title = "Serie mensual de precipitacion",
    x = "Mes",
    y = "Precipitacion (mm)",
    fill = "Sitio"
  ) +
  theme_minimal(base_size = 12)

8 Mapas de similaridad climatica

Para cada punto del Valle del Cauca se calcula la distancia euclidiana entre su clima mensual y el clima de cada celda del mundo. Antes de calcular la distancia, cada variable se estandariza para que temperatura y precipitacion sean comparables.

media_capas <- as.numeric(terra::global(clima_stack, "mean", na.rm = TRUE)[, 1])
sd_capas <- as.numeric(terra::global(clima_stack, "sd", na.rm = TRUE)[, 1])

clima_stack_z <- (clima_stack - media_capas) / sd_capas

clima_puntos_raw <- terra::extract(clima_stack, puntos_vect) |>
  select(-ID) |>
  as.matrix()

clima_puntos_z <- sweep(clima_puntos_raw, 2, media_capas, "-")
clima_puntos_z <- sweep(clima_puntos_z, 2, sd_capas, "/")

calcular_distancia <- function(raster_z, referencia_z) {
  terra::app(raster_z, fun = function(x) {
    if (is.null(dim(x))) {
      return(sqrt(sum((x - referencia_z)^2)))
    }
    sqrt(rowSums((x - matrix(
      referencia_z,
      nrow = nrow(x),
      ncol = length(referencia_z),
      byrow = TRUE
    ))^2))
  })
}

mapas_similaridad <- list()

for (i in seq_len(nrow(puntos_valle))) {
  distancia_i <- calcular_distancia(clima_stack_z, clima_puntos_z[i, ])
  similaridad_i <- 1 / (1 + distancia_i)
  similaridad_i <- terra::mask(similaridad_i, mascara_tierra)
  names(similaridad_i) <- paste0("similaridad_", puntos_valle$sitio[i])
  mapas_similaridad[[puntos_valle$sitio[i]]] <- similaridad_i

  plot(
    similaridad_i,
    col = pal_sim,
    main = paste("Similaridad climatica global con", puntos_valle$sitio[i])
  )
  points(puntos_vect[i], pch = 19, col = "red", cex = 1.1)
}

similaridad_promedio <- mean(terra::rast(mapas_similaridad), na.rm = TRUE)
similaridad_promedio <- terra::mask(similaridad_promedio, mascara_tierra)
names(similaridad_promedio) <- "similaridad_promedio_valle"

plot(
  similaridad_promedio,
  col = pal_sim,
  main = "Similaridad climatica promedio con puntos del Valle del Cauca"
)
points(puntos_vect, pch = 19, col = "red", cex = 1.1)

resumen_similaridad <- bind_rows(
  lapply(names(mapas_similaridad), function(nombre) {
    resumen_raster(mapas_similaridad[[nombre]], nombre, umbral_alto = 0.25)
  })
) |>
  bind_rows(
    resumen_raster(similaridad_promedio, "Promedio Valle del Cauca", umbral_alto = 0.25)
  ) |>
  rename(area_similaridad_025_km2 = area_alta_km2)

knitr::kable(
  resumen_similaridad,
  digits = 3,
  caption = "Resumen estadistico de los mapas de similaridad climatica"
)
Resumen estadistico de los mapas de similaridad climatica
mapa minimo promedio maximo p75 p90 area_similaridad_025_km2
Palmira 0.024 0.128 1.000 0.144 0.175 4493326
El Cerrito 0.024 0.128 1.000 0.143 0.174 4414183
Buga 0.024 0.124 1.000 0.138 0.168 3801397
Promedio Valle del Cauca 0.024 0.126 0.805 0.142 0.172 4237579

Los mapas de similaridad alcanzan valores maximos cercanos a 1 en torno a los puntos de referencia, como resultado de la distancia euclidiana minima entre cada sitio y su entorno climatico inmediato. El mapa promedio del Valle del Cauca tiene un valor medio global de 0.126 y un percentil 90 de 0.172. Las areas con similaridad igual o superior a 0.25 representan 4,237,579 km2, concentradas principalmente en regiones tropicales con regimenes termicos y pluviometricos comparables.

writeRaster(
  terra::rast(mapas_similaridad),
  file.path(dir_salida, "similaridad_climatica_puntos_valle.tif"),
  overwrite = TRUE
)

writeRaster(
  similaridad_promedio,
  file.path(dir_salida, "similaridad_promedio_valle.tif"),
  overwrite = TRUE
)

9 Comparacion de aproximaciones

umbral_sim_alta <- percentil_global(similaridad_promedio, 0.90)
area_coincidente_km2 <- area_condicion(
  aptitud_cana >= umbral_alto & similaridad_promedio >= umbral_sim_alta,
  aptitud_cana
)

tabla_comparacion <- data.frame(
  indicador = c(
    "Area con aptitud alta",
    "Area estrictamente optima",
    "Umbral de similaridad alta",
    "Area coincidente entre aptitud alta y similaridad alta"
  ),
  valor = c(
    paste0(fmt_num(area_alta_global_km2, 0), " km2"),
    paste0(fmt_num(area_optima_km2, 0), " km2"),
    fmt_num(umbral_sim_alta, 3),
    paste0(fmt_num(area_coincidente_km2, 0), " km2")
  )
)

knitr::kable(
  tabla_comparacion,
  caption = "Indicadores de comparacion entre aptitud y similaridad"
)
Indicadores de comparacion entre aptitud y similaridad
indicador valor
Area con aptitud alta 18,114,540 km2
Area estrictamente optima 347,510 km2
Umbral de similaridad alta 0.172
Area coincidente entre aptitud alta y similaridad alta 6,887,939 km2
par(mfrow = c(2, 1), mar = c(3, 3, 3, 5))
plot(
  aptitud_cana,
  col = pal_aptitud,
  main = "Aptitud por rangos optimos de cana de azucar"
)
plot(
  similaridad_promedio,
  col = pal_sim,
  main = "Similaridad climatica con puntos del Valle del Cauca"
)

par(mfrow = c(1, 1))

Los mapas de aptitud y similaridad responden preguntas relacionadas, pero no identicas. La aptitud por rangos optimos identifica zonas que satisfacen las condiciones agroclimaticas generales del cultivo, mientras que la similaridad identifica regiones cuyo ciclo mensual de temperatura y precipitacion se parece al de Palmira, El Cerrito y Buga.

La diferencia principal se observa en la precipitacion. Los puntos del Valle del Cauca presentan precipitacion anual inferior al rango optimo definido para el cultivo, aunque conservan una estacionalidad compatible con zonas productoras tropicales. Por esta razon, el mapa de similaridad puede resaltar zonas analogas al Valle del Cauca que no necesariamente cumplen todos los rangos optimos de aptitud.

10 Priorizacion climatica integrada

prioridad_climatica <- aptitud_cana * similaridad_promedio
prioridad_climatica <- terra::mask(prioridad_climatica, mascara_tierra)
names(prioridad_climatica) <- "prioridad_climatica"

umbral_prioridad_alta <- percentil_global(prioridad_climatica, 0.90)
area_prioridad_alta_km2 <- area_condicion(
  prioridad_climatica >= umbral_prioridad_alta,
  prioridad_climatica
)

resumen_prioridad <- resumen_raster(
  prioridad_climatica,
  "Prioridad climatica integrada",
  umbral_alto = umbral_prioridad_alta
)

plot(
  prioridad_climatica,
  col = hcl.colors(100, "YlOrRd", rev = FALSE),
  main = "Prioridad climatica integrada: aptitud x similaridad"
)

writeRaster(
  prioridad_climatica,
  file.path(dir_salida, "prioridad_climatica_integrada.tif"),
  overwrite = TRUE
)

tabla_sintesis <- data.frame(
  indicador = c(
    "Area global con aptitud alta",
    "Area estrictamente optima",
    "Pais con mayor area potencial",
    "Sitio del Valle mas cercano al rango termico optimo",
    "Area con similaridad alta al Valle del Cauca",
    "Area de prioridad climatica integrada alta"
  ),
  resultado = c(
    paste0(fmt_num(area_alta_global_km2, 0), " km2"),
    paste0(fmt_num(area_optima_km2, 0), " km2"),
    paste0(top_paises$NAME_0[1], " (", fmt_num(top_paises$area_alta_km2[1], 0), " km2)"),
    "Palmira",
    paste0(fmt_num(area_coincidente_km2, 0), " km2 coincidentes con aptitud alta"),
    paste0(fmt_num(area_prioridad_alta_km2, 0), " km2")
  )
)

knitr::kable(
  tabla_sintesis,
  caption = "Sintesis ejecutiva de resultados"
)
Sintesis ejecutiva de resultados
indicador resultado
Area global con aptitud alta 18,114,540 km2
Area estrictamente optima 347,510 km2
Pais con mayor area potencial Brazil (5,885,376 km2)
Sitio del Valle mas cercano al rango termico optimo Palmira
Area con similaridad alta al Valle del Cauca 6,887,939 km2 coincidentes con aptitud alta
Area de prioridad climatica integrada alta 25,591,091 km2

El mapa de prioridad climatica integrada combina en una sola capa la aptitud agroclimatica general y la similaridad con los puntos del Valle del Cauca. Los valores mas altos corresponden a regiones que no solo presentan condiciones favorables para cana de azucar, sino que ademas tienen un comportamiento mensual de temperatura y precipitacion comparable al de la zona de referencia. Con el percentil 90 como umbral de prioridad alta (0.088), el area prioritaria estimada es de 25,591,091 km2.

En conclusion, la aptitud climatica integrada es mas adecuada para delimitar zonas potenciales generales para cana de azucar. La similaridad climatica es mas util para identificar analogos del Valle del Cauca. Las areas coincidentes, estimadas en 6,887,939 km2 bajo los umbrales definidos, representan los sitios mas consistentes entre ambas aproximaciones: cumplen condiciones favorables para el cultivo y, al mismo tiempo, se parecen climaticamente a los puntos de referencia regionales.