Densidad del arbolado de Cali con R
Contacto: wa.me/+573217850490
El último censo arbóreo de Cali, que la CVC le entregó al DAGMA en 2024, registró unos 382 mil individuos en la zona urbana (Alcaldía de Cali). Cuando uno pone esos puntos en un mapa, lo que ve es una mancha verde. No dice mucho. La pregunta útil es otra: ¿dónde se concentran y dónde faltan?
Para responder eso hay dos caminos clásicos y en este tutorial hago los dos:
- Raster de conteo. Divido la ciudad en celdas (50, 100 o 250 m) y cuento cuántos árboles caen en cada una. Es directo y fácil de explicar, pero el resultado cambia según el tamaño y la posición de la grilla.
- Densidad kernel (KDE). A cada árbol le pongo una «campana» que reparte su peso alrededor, y sumo todas las campanas. Sale una superficie continua. Aquí lo que manda es el ancho de banda (sigma): con 150 m ves cuadras, con 600 m ves zonas de la ciudad.
Y una aclaración que me preguntan seguido: esto no se hace con kriging. El kriging interpola una variable que existe en todo el espacio (temperatura, precipitación) a partir de muestras. La ubicación de los árboles no es una muestra de nada, es el fenómeno completo. Para eso está el análisis de patrones de puntos, y el kernel es su herramienta base.
La preparación
Datos. Todo sale de fuentes oficiales de la Alcaldía:
| Capa | Fuente | Nota |
|---|---|---|
| Árboles (censo arbóreo) | Geovisor IDESC, descarga directa del censo (censo_arboreo_2023.rar) | Capa obs_arb_censo_arboreo_20241105: 382.021 puntos, en MAGNA-SIRGAS origen Cali |
| Árboles (alternativa) | Datos Abiertos Cali | CSV por comuna; es el censo de 2015, actualizado en 2019 |
| Barrios, comunas y sectores de expansión | DIVIPOLA IDESC | Geodatabase del Acuerdo 0636 de 2026 |
Ojo con el sur: la zona de expansión no tiene barrios adoptados. Está dividida en sectores geográficos, una capa aparte dentro de la misma geodatabase. Si solo cargas barrios, esa zona te queda en blanco. En el script uno barrios y sectores en una sola capa de unidades.
Tipo de registro. La capa del censo tiene 382.021 puntos, pero no todos son árboles. Hay 239.014 árboles (código ARB) y 69.600 palmas (PAL). El resto son otros tipos de vegetación (ABT, GUA, BAM y CBR) o registros sin tipo (ND). Para la densidad uso solo árboles y palmas: si cuentas todo, la densidad de árboles sale inflada.
Sistema de referencia. Trabajo en MAGNA-SIRGAS origen Cali (EPSG:6249), que está en metros. Esto no es opcional: el tamaño de celda, el sigma del kernel y las áreas tienen que estar en metros. En grados (EPSG:4326) los números no significan nada.
Librerías. sf y terra para vector y raster, spatstat.geom y spatstat.explore para el patrón de puntos y el kernel, tidyverse para el manejo de tablas, y ggspatial y patchwork para los mapas.
Comandos clave
sf::st_filter(): antes de todo, me quedo solo con árboles y palmas (ARB y PAL en el campo CaTipoVeg) que caen dentro del área urbana más la de expansión. Si hay puntos duplicados (mismas coordenadas) también los quito, porque inflan la densidad.terra::rasterize(..., fun = length): es el raster de conteo. Cada celda recibe el número de árboles que caen en ella. Luego divido por el área de la celda en hectáreas para tener árboles/ha, y así puedo comparar 50, 100 y 250 m.spatstat.geom::ppp(): convierte los árboles en un patrón de puntos con su «ventana», que es el límite de la ciudad. La ventana importa porque el kernel corrige el efecto de borde con ella.spatstat.explore::bw.scott.iso(): da un ancho de banda de referencia rápido. Hay métodos más finos (bw.diggle,bw.ppl), pero con más de 300 mil puntos se demoran demasiado para un video.spatstat.explore::density.ppp(): el kernel como tal. Le paso el sigma (150, 300 y 600 m) y el tamaño de píxel. Devuelve intensidad por m², que multiplico por 10.000 para llevarla a árboles/ha.sf::st_intersects()+lengths(): el resumen por barrio y comuna. Cuento árboles por polígono y divido por su área. Es la versión «administrativa» de la densidad, la que sirve para decir qué barrio está más pelado.
Un chequeo que siempre hago: si sumo el kernel sobre toda la ciudad (intensidad × área del píxel), me tiene que dar más o menos el número total de árboles. Si no, algo está mal con las unidades.
Con ese chequeo listo, el script arma los mapas con ggspatial (escala y norte) y pone el raster de conteo y el kernel lado a lado con patchwork. Ahí se ve la diferencia: el conteo se ve «pixelado» y con huecos, el kernel suaviza y muestra los corredores verdes.

Para cerrar
En Cali, el arbolado se concentra en el sur, en la comuna 17, y forma núcleos en el occidente (comunas 3 y 19) y en el oriente (comunas 15 y 21). Lo más pelado está en el centro (comunas 7, 9 y 12) y en la ladera de la comuna 20. Por barrio, el que más árboles por hectárea tiene es [BARRIO], con [X] árboles/ha.
El conteo te dice cuántos árboles hay en cada cuadro; el kernel te dice cómo se reparte el arbolado en la ciudad. Los dos sirven, pero para preguntas distintas. Y en ambos casos el resultado depende de una decisión tuya (tamaño de celda o sigma), así que siempre vale la pena mostrar más de uno.
El paso a paso completo, con el código corriendo, está en el canal:
Deja una respuesta