La caña de azúcar es uno de los cultivos agroindustriales más importantes del mundo, con una producción anual para 2010 de cerca de 1.700 millones de toneladas a nivel global y entre 22 y 23 millones de toneladas en Colombia. Su distribución geográfica responde a un conjunto de exigencias particulares en términos de temperatura, precipitación y disponibilidad hídrica.
El presente documento desarrolla una exploración de datos espaciales orientada a identificar zonas climáticas potencialmente aptas para el cultivo de caña de azúcar a nivel global. Para este fin, se parte de la definición de un rango óptimo de cultivo basado en estudios previos y, complementario a este, un segundo enfoque basado en similaridad climática. Este último toma como sitio de referencia al Valle del Cauca (Colombia), donde la caña ya se cultiva con éxito, e identifica zonas del mundo con condiciones análogas al departamento colombiano.
El análisis se apoya en datos climáticos de línea base provenientes
de WorldClim 2.1, que reporta promedios mensuales
históricos de temperatura y precipitación para el período 1970–2000 a
una resolución espacial de 10 minutos de arco. Las fronteras políticas
se toman del paquete rnaturalearth.
El primer enfoque para identificar zonas potencialmente aptas para el cultivo de caña de azúcar consiste en aplicar reglas óptimas de aptitud basadas en estudios previos.
Para la caña de azúcar, los rangos planteados por el estudio son:
Una celda espacial del ráster se considera “apta” cuando cumple simultáneamente ambas condiciones, lo que genera una clasificación binaria de apta o no apta para el cultivo. Esta aproximación representa una limitante en términos de información, pues ignora otras condiciones particulares que, aunque no se clasifican como óptimas, podrían ser más eficientes en términos de capital físico o natural, beneficiando y maximizando la producción o el ingreso de los cultivos de caña.
library(geodata)
library(terra)
library(ggplot2)
library(tidyterra)
library(sf)
library(rnaturalearth)
library(rnaturalearthdata)
tavg <- worldclim_global(var = "tavg", res = 10, path = "data/")
prec <- worldclim_global(var = "prec", res = 10, path = "data/")
tavg_mean <- app(tavg, fun = mean, na.rm = TRUE)
prec_total <- app(prec, fun = sum, na.rm = TRUE)
rm(tavg, prec)
gc()## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 1928114 103.0 3656720 195.3 3143508 167.9
## Vcells 2946305 22.5 8388608 64.0 4508766 34.4
apt_temp <- (tavg_mean >= 22.5 & tavg_mean <= 28)
apt_prec <- (prec_total >= 1500 & prec_total <= 3500)
aptitud <- apt_temp & apt_prec
aptitud_num <- as.numeric(aptitud)
world <- ne_countries(scale = "medium", returnclass = "sf")
ggplot() +
geom_spatraster(data = aptitud_num) +
scale_fill_gradientn(
colors = c("gray95", "#2d6a4f"),
limits = c(0, 1),
na.value = "transparent",
name = "Aptitud climatica\ncana de azucar",
breaks = c(0.1, 0.9),
labels = c("No apto", "Apto")
) +
geom_sf(data = world, fill = NA, color = "white", linewidth = 0.2) +
labs(
title = "Ilustración 1: Aptitud climatica global para cana de azucar",
subtitle = "Temperatura optima: 22.5-28 C | Precipitacion anual: 1500-3500 mm",
caption = "Fuente: WorldClim 2.1 | Periodo de referencia: 1970-2000"
) +
coord_sf(expand = FALSE) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(size = 10, color = "gray40"),
plot.caption = element_text(size = 8, color = "gray60"),
legend.position = "bottom",
legend.key.width = unit(3, "cm"),
legend.key.height = unit(0.4, "cm"),
panel.background = element_rect(fill = "#d0e8f5", color = NA),
panel.grid = element_line(color = "white", linewidth = 0.3)
)La ilustración 1 presenta el mapa global resultante de aplicar los rangos optimos de temperatura y precipitación a los datos de WorldClim 2.1, generando una clasificación binaria de aptitud para el cultivo de la caña de azúcar. El patron espacial obtenido se concentra en una franja cerca de la linea del Ecuador.
Las principales regiones identificadas como aptas son:
América: Los paises Suramericanos de (Colombia, Ecuador, Perú, oeste de Brasil) y partes de Centroamérica (Panamá, Costa Rica, Nicaragua)
África: La cuenca del Congo, la costa del Golfo de Guinea (Costa de Marfil, Ghana, Camerún) y la gran isla de Madagascar.
Asia y Oceanía: El Sudeste Asiático insular (Indonesia, Malasia, Filipinas, Papúa Nueva Guinea) y porciones del Sudeste Asiático continental (Tailandia, Vietnam, Camboya).
Es llamativo que países exportadores de caña o sus derivados no aparecen tan marcados en el mapa, ejemplo como Cuba , la India o Mexico. Lo que indicaría que las aptitudes climáticas planteadas, aunque pueden ser necesarias, no son estrictamente excluyentes.
Con el propósito de contrastar esta información, presentamos la distribución de las áreas cultivadas de caña de azúcar según el dataset SPAM 2010 v2.0 (IFPRI / Harvard). Esto permite evidenciar contraste entre las zonas climáticamente aptas basadas en los conceptos planteados y los territorios donde realmente se explota el cultivo.
cana <- crop_spam(crop = "sugarcane", var = "area", path = "data/")
cana_total <- sum(cana, na.rm = TRUE)
cana_total[cana_total == 0] <- NA
cana_log <- log10(cana_total + 1)
ggplot() +
geom_sf(data = world, fill = "gray95", color = "gray70", linewidth = 0.2) +
geom_spatraster(data = cana_log) +
scale_fill_whitebox_c(
palette = "muted",
na.value = "transparent",
name = "Area cosechada\n(ha por celda, escala log)",
breaks = c(0, 1, 2, 3, 4),
labels = c("1", "10", "100", "1.000", "10.000")
) +
geom_sf(data = world, fill = NA, color = "gray40", linewidth = 0.2) +
labs(
title = "Ilustracion 2. Distribucion global del cultivo de cana de azucar",
subtitle = "Area cosechada ",
caption = "Fuente: SPAM 2010 v2.0 (IFPRI)"
) +
coord_sf(expand = FALSE) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(size = 10, color = "gray40"),
plot.caption = element_text(size = 8, color = "gray60"),
legend.position = "bottom",
legend.key.width = unit(3, "cm"),
legend.key.height = unit(0.4, "cm"),
panel.background = element_rect(fill = "#d0e8f5", color = NA),
panel.grid = element_line(color = "white", linewidth = 0.3)
)La Ilustración 2 presenta la distribución global de las áreas cosechadas de caña de azúcar (en escala logarítmica), permitiendo contrastar la producción real frente al modelo de aptitud climática en base a los rangos establecidos. Al comparar ambos análisis, saltan a la vista importantes diferencias: existen regiones clasificadas inicialmente como ‘no óptimas’ que, sin embargo, registran una alta densidad de cultivo, y viceversa.
El caso de Brasil es el ejemplo más claro de este contraste: mientras que la Amazonía (zona norte) exhibe las mejores condiciones climáticas teóricas pero la ilustración 2 ilustra poca actividad de cultivo, mientras que el centro-sur del país especialmente el estado de São Paulo concentra el mayor núcleo de producción global a pesar de ubicarse fuera de la franja óptima. Un fenómeno similar ocurre en el norte y centro de la India y en la isla de Cuba, entre otras regiones.
library(terra)
cana_total_rs <- resample(cana_total, aptitud_num, method = "average")
cana_bin <- as.numeric(cana_total_rs > 0)
comparacion <- aptitud_num + (cana_bin * 2)
comparacion <- as.factor(comparacion)
levels(comparacion) <- data.frame(
id = 0:3,
clase = c("Ni apto ni cultivado",
"Apto sin cultivar",
"Cultivado fuera de optimo",
"Apto y cultivado")
)
ggplot() +
geom_sf(data = world, fill = "gray95", color = "gray70", linewidth = 0.2) +
geom_spatraster(data = comparacion) +
scale_fill_manual(
values = c("Ni apto ni cultivado" = "gray95",
"Apto sin cultivar" = "#a8dadc",
"Cultivado fuera de optimo" = "#e63946",
"Apto y cultivado" = "#2d6a4f"),
na.value = "transparent",
name = NULL
) +
geom_sf(data = world, fill = NA, color = "gray40", linewidth = 0.2) +
labs(
title = "Ilustracion 3. Validacion: aptitud vs cultivo real",
subtitle = "Coincidencia entre requerimientos teoricos y la distribucion real",
caption = "Fuentes: WorldClim 2.1 | SPAM 2010 "
) +
coord_sf(expand = FALSE) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 12),
plot.subtitle = element_text(size = 10, color = "gray40"),
plot.caption = element_text(size = 8, color = "gray60"),
legend.position = "bottom",
panel.background = element_rect(fill = "#d0e8f5", color = NA),
panel.grid = element_line(color = "white", linewidth = 0.3)
)Finalmente, la Ilustración 3 presenta la comparación entre los cultivos ubicados en zonas identificadas como aptas (en verde) y los cultivos reales que caen por fuera de los rangos climáticos establecidos (en rojo). Como se observa, existe una cantidad importante de cultivos por fuera de las áreas estimadas previamente. Este contraste invita a reevaluar si los rangos planteados inicialmente son los más adecuados, o en su defecto, a construir un modelo que permita medir el impacto marginal de estas variables climaticas sobre la presencia de los cultivos.
Habiendo identificado a nivel global las regiones climáticamente aptas (Según los rangos establecidos por el estudio) para el cultivo de caña de azúcar, resulta útil descender a una escala nacional para apreciar con mayor detalle la distribución interna de aptitud de tres paises seleccionados.
Se seleccionaron tres paises:
Colombia: Uno de los principales productores a nivel mundial con 23,5 millones de toneladas de caña al año.
Brasil: Brasil es el mayor productor mundial de caña de azúcar, generando más del 40 % de la producción global con volúmenes que superan las 700 millones de toneladas anuales.
República Democrática del Congo: El caso de contraste. Aunque su producción es incipiente a escala global (apenas 2,4 millones de toneladas), el modelo lo identifica como un territorio con condiciones climáticas teóricamente óptimas para la caña de azúcar.
library(terra)
library(ggplot2)
library(tidyterra)
library(sf)
library(patchwork)
paises <- world[world$name %in% c("Colombia", "Brazil", "Dem. Rep. Congo"), ]
apt_colombia <- mask(crop(aptitud_num, paises[paises$name == "Colombia", ]),
paises[paises$name == "Colombia", ])
apt_brasil <- mask(crop(aptitud_num, paises[paises$name == "Brazil", ]),
paises[paises$name == "Brazil", ])
apt_congo <- mask(crop(aptitud_num, paises[paises$name == "Dem. Rep. Congo", ]),
paises[paises$name == "Dem. Rep. Congo", ])
mapa_pais <- function(raster, shape, titulo) {
ggplot() +
geom_sf(data = shape, fill = "gray95", color = "gray70", linewidth = 0.3) +
geom_spatraster(data = raster) +
scale_fill_gradientn(
colors = c("gray95", "#2d6a4f"),
limits = c(0, 1),
na.value = "transparent",
name = "Aptitud",
breaks = c(0.1, 0.9),
labels = c("No apto", "Apto")
) +
geom_sf(data = shape, fill = NA, color = "black", linewidth = 0.4) +
labs(title = titulo) +
coord_sf(expand = FALSE) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 12),
legend.position = "bottom",
legend.key.width = unit(2, "cm"),
legend.key.height = unit(0.4, "cm"),
panel.background = element_rect(fill = "#d0e8f5", color = NA),
panel.grid = element_line(color = "white", linewidth = 0.3),
axis.text = element_text(size = 7)
)
}
p_colombia <- mapa_pais(apt_colombia,
paises[paises$name == "Colombia", ],
"Colombia")
p_brasil <- mapa_pais(apt_brasil,
paises[paises$name == "Brazil", ],
"Brasil")
p_congo <- mapa_pais(apt_congo,
paises[paises$name == "Dem. Rep. Congo", ],
"Rep. Dem. del Congo")
(p_colombia | p_brasil | p_congo) +
plot_annotation(
title = "Ilustracion 4. Aptitud climatica por pais",
subtitle = "Temperatura optima: 22.5-28 C | Precipitacion: 1500-3500 mm",
caption = "Fuente: WorldClim 2.1 | Periodo de referencia: 1970-2000",
theme = theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(size = 10, color = "gray40"),
plot.caption = element_text(size = 8, color = "gray60")
)
)La Ilustración 4 presenta las zonas óptimas para los tres países previamente seleccionados: Colombia, Brasil y la República Democrática del Congo. Aquí se observa esa diferencia clave que vimos en el mapa comparativo global, donde las zonas de mayor aptitud climática no corresponden necesariamente a los territorios con tradición en el cultivo de caña. Tanto para Colombia como para Brasil, la zona óptima se concentra en la región amazónica; áreas que suelen ser protegidas y que presentan condiciones logísticas muy complicadas para la agroindustria. Curiosamente, el modelo deja por fuera las zonas históricas y de mayor producción real, como lo son el Valle del Cauca para Colombia, y el estado de São Paulo (centro-sur) para el caso brasileño. Por su parte, la RDC presenta sus propias lógicas internas de subdesarrollo: la falta de una agroindustria fuerte, los conflictos sociales y la violencia, sumados a la vasta presencia de selva tropical, explican su baja producción de caña a nivel mundial a pesar de su potencial climático.
library(terra)
library(ggplot2)
library(tidyterra)
library(sf)
library(patchwork)
comp_colombia <- mask(crop(comparacion, paises[paises$name == "Colombia", ]),
paises[paises$name == "Colombia", ])
comp_brasil <- mask(crop(comparacion, paises[paises$name == "Brazil", ]),
paises[paises$name == "Brazil", ])
comp_congo <- mask(crop(comparacion, paises[paises$name == "Dem. Rep. Congo", ]),
paises[paises$name == "Dem. Rep. Congo", ])
mapa_comp_pais <- function(raster, shape, titulo) {
ggplot() +
geom_sf(data = shape, fill = "gray95", color = "gray70", linewidth = 0.3) +
geom_spatraster(data = raster) +
scale_fill_manual(
values = c("Ni apto ni cultivado" = "gray95",
"Apto sin cultivar" = "#a8dadc",
"Cultivado fuera de optimo" = "#e63946",
"Apto y cultivado" = "#2d6a4f"),
na.value = "transparent",
name = NULL,
drop = FALSE
) +
geom_sf(data = shape, fill = NA, color = "black", linewidth = 0.4) +
labs(title = titulo) +
coord_sf(expand = FALSE) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 12),
legend.position = "bottom",
legend.text = element_text(size = 7),
panel.background = element_rect(fill = "#d0e8f5", color = NA),
panel.grid = element_line(color = "white", linewidth = 0.3),
axis.text = element_text(size = 7)
)
}
pc_colombia <- mapa_comp_pais(comp_colombia,
paises[paises$name == "Colombia", ],
"Colombia")
pc_brasil <- mapa_comp_pais(comp_brasil,
paises[paises$name == "Brazil", ],
"Brasil")
pc_congo <- mapa_comp_pais(comp_congo,
paises[paises$name == "Dem. Rep. Congo", ],
"Rep. Dem. del Congo")
(pc_colombia | pc_brasil | pc_congo) +
plot_layout(guides = "collect") +
plot_annotation(
title = "Ilustracion 5. Cultivo real vs zonas optimas identificadas por pais",
subtitle = "Comparacion entre aptitud climatica y distribucion real (SPAM 2010)",
caption = "Fuentes: WorldClim 2.1 | SPAM 2010 v2.0 (IFPRI)",
theme = theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(size = 10, color = "gray40"),
plot.caption = element_text(size = 8, color = "gray60"),
legend.position = "bottom"
)
) &
theme(legend.position = "bottom")La Ilustración 5 expone a nivel nacional para los tres paises seleccionados la gran discrepancia del análisis: el contraste entre las zonas con aptitud climática planteada y la realidad agrícola. Queda en evidencia una fuerte concentración de cultivos (marcados en rojo) que se desarrollan de manera exitosa totalmente por fuera de los rangos óptimos previamente identificados.
Para caracterizar climáticamente el Valle del Cauca se realiza un muestreo aleatorio simple sobre la región. El procedimiento consiste en recortar el ráster climático global al área del departamento y luego seleccionar tres puntos al azar entre las celdas válidas todos con la misma probabilidad de selección.
library(terra)
library(ggplot2)
library(tidyterra)
library(sf)
library(geodata)
library(patchwork)
colombia_dep <- gadm(country = "COL", level = 1, path = "data/")
valle <- colombia_dep[colombia_dep$NAME_1 == "Valle del Cauca", ]
tavg <- worldclim_global(var = "tavg", res = 2.5, path = "data/")
prec <- worldclim_global(var = "prec", res = 2.5, path = "data/")
tavg_valle <- mask(crop(tavg, valle), valle)
prec_valle <- mask(crop(prec, valle), valle)
tavg_anual_valle <- mean(tavg_valle)
prec_anual_valle <- sum(prec_valle)
set.seed(1506)
puntos_sp <- spatSample(tavg_anual_valle, size = 3,
method = "random",
na.rm = TRUE,
as.points = TRUE)
puntos_sf <- st_as_sf(puntos_sp)
valle_sf <- st_as_sf(valle)
dentro <- st_within(puntos_sf, valle_sf, sparse = FALSE)[, 1]
if (any(!dentro)) {
warning("Algunos puntos cayeron en celdas borde. Re-muestreando...")
set.seed(456)
puntos_sp <- spatSample(tavg_anual_valle, size = 3,
method = "random", na.rm = TRUE,
as.points = TRUE)
}
coords <- crds(puntos_sp)
puntos_info <- data.frame(
sitio = paste0("Punto ", 1:3),
lon = round(coords[, 1], 3),
lat = round(coords[, 2], 3)
)
print(puntos_info)## sitio lon lat
## 1 Punto 1 -76.271 3.312
## 2 Punto 2 -76.021 4.854
## 3 Punto 3 -76.479 3.812
mapa_temp <- ggplot() +
geom_spatraster(data = tavg_anual_valle) +
scale_fill_gradientn(
colors = c("#fef3c7", "#fb923c", "#dc2626"),
na.value = "transparent",
name = "Temperatura\nanual (C)",
guide = guide_colorbar(barwidth = 8, barheight = 0.5,
title.position = "top")
) +
geom_sf(data = valle_sf, fill = NA, color = "black", linewidth = 0.5) +
geom_sf(data = st_as_sf(puntos_sp), color = "blue", size = 3) +
geom_sf_label(data = st_as_sf(puntos_sp),
aes(label = paste0("P", 1:3)),
nudge_y = 0.05, size = 3.5, fontface = "bold") +
labs(title = "Temperatura media anual",
x = NULL, y = NULL) +
coord_sf(expand = FALSE) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 12),
legend.position = "bottom",
legend.title = element_text(size = 9),
legend.text = element_text(size = 8),
panel.background = element_rect(fill = "#d0e8f5", color = NA),
axis.text = element_text(size = 7)
)
mapa_prec <- ggplot() +
geom_spatraster(data = prec_anual_valle) +
scale_fill_gradientn(
colors = c("#fef9c3", "#86efac", "#1d4ed8"),
na.value = "transparent",
name = "Precipitacion\nanual (mm)",
guide = guide_colorbar(barwidth = 8, barheight = 0.5,
title.position = "top")
) +
geom_sf(data = valle_sf, fill = NA, color = "black", linewidth = 0.5) +
geom_sf(data = st_as_sf(puntos_sp), color = "red", size = 3) +
geom_sf_label(data = st_as_sf(puntos_sp),
aes(label = paste0("P", 1:3)),
nudge_y = 0.05, size = 3.5, fontface = "bold") +
labs(title = "Precipitacion anual acumulada",
x = NULL, y = NULL) +
coord_sf(expand = FALSE) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 12),
legend.position = "bottom",
legend.title = element_text(size = 9),
legend.text = element_text(size = 8),
panel.background = element_rect(fill = "#d0e8f5", color = NA),
axis.text = element_text(size = 7)
)
(mapa_temp | mapa_prec) +
plot_annotation(
title = "Ilustracion 6. Puntos de muestreo en el Valle del Cauca",
subtitle = "Muestreo aleatorio simple sobre el raster climatico (3 puntos)",
caption = "Fuente: WorldClim 2.1 (res. 2.5 arc-min) | Limite GADM",
theme = theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(size = 10, color = "gray40"),
plot.caption = element_text(size = 8, color = "gray60")
)
)library(sf)
library(geodata)
col_mun <- gadm(country = "COL", level = 2, path = "data/")
col_mun_sf <- st_as_sf(col_mun)
puntos <- data.frame(
sitio = c("Punto 1", "Punto 2", "Punto 3"),
lon = c(-76.271, -76.021, -76.479),
lat = c( 3.312, 4.854, 3.812)
)
puntos_sf <- st_as_sf(puntos, coords = c("lon", "lat"), crs = 4326)
resultado <- st_join(puntos_sf, col_mun_sf[, c("NAME_1", "NAME_2")])
print(resultado)## Simple feature collection with 3 features and 3 fields
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: -76.479 ymin: 3.312 xmax: -76.021 ymax: 4.854
## Geodetic CRS: WGS 84
## sitio NAME_1 NAME_2 geometry
## 1 Punto 1 Valle del Cauca Florida POINT (-76.271 3.312)
## 2 Punto 2 Valle del Cauca El Águila POINT (-76.021 4.854)
## 3 Punto 3 Valle del Cauca Restrepo POINT (-76.479 3.812)
La Ilustración 6 detalla los tres municipios seleccionados mediante un muestreo aleatorio simple en el departamento del Valle del Cauca: Florida (punto 1, al sur), El Águila (punto 2, al norte en zona montañosa) y Restrepo (punto 3, ubicado hacia el centro del departamento). Tambien presenta la temperatura media anual y la precipitación anual promedio del departamento del valle del Cauca.
puntos <- data.frame(
sitio = c("Florida", "El Águila", "Restrepo"),
lon = c(-76.271, -76.021, -76.479),
lat = c( 3.312, 4.854, 3.812)
)
puntos_sf <- st_as_sf(puntos, coords = c("lon", "lat"), crs = 4326)
temp_puntos <- extract(tavg, puntos_sf)
prec_puntos <- extract(prec, puntos_sf)
meses <- c("Ene","Feb","Mar","Abr","May","Jun",
"Jul","Ago","Sep","Oct","Nov","Dic")
temp_long <- data.frame(
mes_num = rep(1:12, times = nrow(puntos)),
valor = as.vector(t(as.matrix(temp_puntos[,-1]))),
sitio = rep(puntos$sitio, each = 12)
)
prec_long <- data.frame(
mes_num = rep(1:12, times = nrow(puntos)),
valor = as.vector(t(as.matrix(prec_puntos[,-1]))),
sitio = rep(puntos$sitio, each = 12)
)
p_temp <- ggplot(temp_long, aes(x = mes_num, y = valor)) +
annotate("rect", xmin = 0.5, xmax = 12.5, ymin = 22.5, ymax = 28,
fill = "#2d6a4f", alpha = 0.12) +
annotate("text", x = 12.3, y = 27.5, label = "Rango óptimo",
hjust = 1, size = 3, color = "#2d6a4f", fontface = "italic") +
geom_line(aes(color = sitio, group = sitio), linewidth = 1.2) +
geom_point(aes(color = sitio), size = 2.5) +
scale_x_continuous(breaks = 1:12, labels = meses) +
scale_color_manual(values = c("#e63946", "#2a9d8f", "#f4a261")) +
labs(
title = "Temperatura media mensual",
subtitle = "Promedio climático 1970–2000 | Rango óptimo caña: 22.5–28 °C",
x = "Mes",
y = "Temperatura (°C)",
color = "Municipio"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 13),
plot.subtitle = element_text(size = 10, color = "gray40"),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
p_prec <- ggplot(prec_long, aes(x = mes_num, y = valor)) +
annotate("rect", xmin = 0.5, xmax = 12.5, ymin = 125, ymax = 290,
fill = "#1d4ed8", alpha = 0.12) +
annotate("text", x = 12.3, y = 280, label = "Rango óptimo",
hjust = 1, size = 3, color = "#1d4ed8", fontface = "italic") +
geom_line(aes(color = sitio, group = sitio), linewidth = 1.2) +
geom_point(aes(color = sitio), size = 2.5) +
scale_x_continuous(breaks = 1:12, labels = meses) +
scale_color_manual(values = c("#e63946", "#2a9d8f", "#f4a261")) +
labs(
title = "Precipitación mensual",
subtitle = "Promedio climático 1970–2000 | Rango óptimo caña: 125–290 mm/mes",
x = "Mes",
y = "Precipitación (mm)",
color = "Municipio"
) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 13),
plot.subtitle = element_text(size = 10, color = "gray40"),
legend.position = "bottom",
panel.grid.minor = element_blank()
)
(p_temp / p_prec) +
plot_annotation(
title = "Ilustración 7. Clima en puntos seleccionados del Valle del Cauca",
subtitle = "Florida (sur), El Águila (norte), Restrepo (centro-occidente)",
caption = "Fuente: WorldClim 2.1 | Período de referencia: 1970–2000",
theme = theme(
plot.title = element_text(face = "bold", size = 15),
plot.subtitle = element_text(size = 10, color = "gray40"),
plot.caption = element_text(size = 8, color = "gray60")
)
)La Ilustración 7 muestra el comportamiento climático mensual promedio de los tres puntos seleccionados aleatoriamente mediante muestreo simple, junto con las franjas de aptitud óptima para el cultivo de caña definidas previamente. En cuanto a la temperatura, únicamente el Punto 1 (Florida) se mantiene dentro del rango óptimo (22.5–28 °C) a lo largo de todo el año. Los otros dos puntos quedan consistentemente por debajo del umbral. Respecto a la precipitación, el comportamiento es más variable: los tres puntos alternan meses dentro y fuera del rango óptimo (125–290 mm/mes).
Es importante señalar que los datos de WorldClim corresponden a promedios de clima del período 1970–2000 y no a observaciones para un periodo t, por lo que no resulta posible construir una serie de tiempo en sentido estricto.
library(geodata)
library(terra)
library(ggplot2)
library(tidyterra)
library(sf)
library(patchwork)
library(rnaturalearth)
library(scales)
tavg <- worldclim_global(var = "tavg", res = 10, path = "data/")
prec <- worldclim_global(var = "prec", res = 10, path = "data/")
puntos <- data.frame(
sitio = c("Florida", "El Águila", "Restrepo"),
lon = c(-76.271, -76.021, -76.479),
lat = c( 3.312, 4.854, 3.812)
)
puntos_sf <- st_as_sf(puntos, coords = c("lon", "lat"), crs = 4326)
temp_pts <- extract(tavg, puntos_sf)[,-1]
prec_pts <- extract(prec, puntos_sf)[,-1]
clima_pts <- cbind(temp_pts, prec_pts)
rownames(clima_pts) <- puntos$sitio
clima_global <- c(tavg, prec)
medias <- global(clima_global, "mean", na.rm = TRUE)[,1]
desvs <- global(clima_global, "sd", na.rm = TRUE)[,1]
clima_global_std <- (clima_global - medias) / desvs## |---------|---------|---------|---------|========================================= |---------|---------|---------|---------|=========================================
clima_pts_std <- sweep(clima_pts, 2, medias, FUN = "-")
clima_pts_std <- sweep(clima_pts_std, 2, desvs, FUN = "/")
calcular_similaridad <- function(stack_global, vector_punto) {
vec <- as.numeric(vector_punto)
dist_pixel <- function(x) {
if (any(is.na(x))) return(NA)
sqrt(sum((x - vec)^2))
}
app(stack_global, fun = dist_pixel)
}
sim_florida <- calcular_similaridad(clima_global_std, clima_pts_std[1, ])## |---------|---------|---------|---------|=========================================
## |---------|---------|---------|---------|=========================================
## |---------|---------|---------|---------|=========================================
world <- ne_countries(scale = "medium", returnclass = "sf")
mapa_similaridad <- function(raster_sim, titulo) {
raster_log <- log1p(raster_sim)
vals <- values(raster_log, na.rm = TRUE)
cortes <- quantile(vals, probs = c(0, 0.05, 0.20, 0.40, 0.60, 0.80, 1), na.rm = TRUE)
ggplot() +
geom_spatraster(data = raster_log) +
scale_fill_gradientn(
colors = c(
"#00441b",
"#1a9850",
"#66bd63",
"#a6d96a",
"#d9f0a3",
"#f7fcf5",
"#ffffff"
),
values = scales::rescale(cortes),
na.value = "transparent",
name = "Distancia\n(log)",
guide = guide_colorbar(
barwidth = unit(10, "cm"),
barheight = unit(0.5, "cm"),
title.position = "top",
title.hjust = 0.5
)
) +
geom_sf(data = world, fill = NA, color = "gray30", linewidth = 0.2) +
labs(
title = titulo,
subtitle = "Verde oscuro: clima idéntico | Blanco: clima totalmente diferente",
caption = "Fuente: WorldClim 2.1 | Período de referencia: 1970–2000"
) +
coord_sf(expand = FALSE) +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 13),
plot.subtitle = element_text(size = 10, color = "gray40"),
plot.caption = element_text(size = 8, color = "gray60"),
legend.position = "bottom",
panel.background = element_rect(fill = "#d0e8f5", color = NA),
panel.grid = element_line(color = "white", linewidth = 0.3),
axis.text = element_text(size = 7, color = "gray50")
)
}Las ilustraciones 8a, 8b y 8c presentan los mapas de similaridad climática global para cada uno de los tres puntos seleccionados en el Valle del Cauca de forma aleatoria. Cada mapa muestr qué tan parecido es su clima al del punto de referencia. La métrica empleada fue la distancia euclidiana. Para evitar que la precipitación dominara el cálculo las variables se estandarizaron. Posteriormente, se aplicó una transformación logarítmica sobre las distancias con el fin de asentuar las diferencias.
En los mapas, los tonos verde oscuro identifican regiones con clima muy similar al punto de referencia, y lo blanco a puntos climaticos opuestos.
Al comparar ambas aproximaciones, se observan diferencias importantes en sus alcances y limitaciones. La primera metodología, basada en rangos óptimos previamente definidos, identifica zonas aptas para el cultivo a partir de rangos fijos de temperatura y precipitación. Su principal ventaja es la investigación previa con base en la literatura de caña existente. Sin embargo, presenta la limitación de generar un resultado binario (apto/no apto), que no captura valores intermedios ni otras variables que pueden afectar el cultivo de caña.
La segunda aproximación, basada en la distancia euclidiana respecto a puntos de referencia, ofrece una medida continua de similitud climática que permite identificar zonas similares a nivel global. No obstante, presenta varias limitaciones. En primer lugar, los mapas resultantes muestran regiones de similitud muy amplias porque la métrica solo evalúa la distancia euclidiana al espacio climático. A esto se suma una limitación propia del diseño del muestreo: los tres puntos se seleccionaron mediante muestreo aleatorio simple sobre la totalidad del Valle del Cauca, no exclusivamente sobre las zonas históricamente cañeras del departamento. Como consecuencia, dos de los tres puntos (El Águila y Restrepo) no son zonas netamente cañeras.
Para un análisis más representativo, sería preferible un muestreo estratificado o restringido a los polígonos con producción de caña e incolporando el rendimiento por hectárea.
En conclusión, ambos enfoques pueden ser complementarios, corrigiendo los problemas de muestreo, pero para futuros estudios se recomienda incorporar otras variables clave para el cultivo de caña, como la altitud, la disponibilidad hídrica (ríos o cuencas utilizables), la historia cañera, el desarrollo industrial, la conectividad, etc.