santiago delgado franco
Este cuaderno explica cómo hacer mapas temáticos para la producción agrícola. Para ello necesitamos dos archivos para empezar: un archivo CSV con los datos de la producción agrícola por municipio (EVA2020) y un geopackage con los municipios de nuestro departamento de estudio. Más adelante usaremos un archivo con las vías de los municipios.
requerimos tener instaladas las librerias y cargarlas dpyar,tmap y sf
library(dplyr)
Aviso: package ‘dplyr’ was built under R version 4.4.2
Adjuntando el paquete: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(tmap)
Aviso: package ‘tmap’ was built under R version 4.4.3
library(sf)
Linking to GEOS 3.13.0, GDAL 3.10.1, PROJ 9.5.1; sf_use_s2() is TRUE
library(readr)
Aviso: package ‘readr’ was built under R version 4.4.3
para este cuaderno trabajaremos con el departamento de antioquia antes de empezar trabajaremos en el folder /GB02/proyecto 6 en donde se encuentran nuestros archivos a analizar geopackage del departamento de antioquia y sus municipios y csv file con EVA 2020 con las estadiscticas de los cultivos
list.files()
[1] "cuarderno 6.nb.html"
[2] "cuarderno 6.Rmd"
[3] "cuarderno.nb.html"
[4] "EVA"
[5] "FRUTALES.csv"
[6] "How to read and subset .xlsx agricultural statistics data"
[7] "mapa produccion final.Rmd"
[8] "mapa produccion.nb.html"
[9] "mapa produccion.Rmd"
[10] "MGN2025_ADM_MPIO_GRAFICO_(Geopackage)"
ahora procedemos a leer y cargar el archivo csv
frutales <- read_delim("FRUTALES.csv", delim = ";", locale = locale(encoding = "UTF-8"))
Rows: 654 Columns: 18
── Column specification ────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ";"
chr (10): Departamento, Código Dane municipio, Municipio, Grupo cultivo, Subgrupo, Cultivo, Desagregación cu...
dbl (8): Código Dane departamento, Año, Periodo, Área sembrada, Área cosechada, Producción, Rendimiento, Có...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
y cargamos los municipios del Geopackage
(municipios = st_read('municipios.gpkg'))
Reading layer `municipios' from data source
`C:\Users\Biblio\Desktop\proyecto 5-20261108T170448Z-1-001-20261111T154808Z-1-001\proyecto 5-20261108T170448Z-1-001\proyecto 5\entrega\municipios.gpkg'
using driver `GPKG'
Simple feature collection with 1122 features and 11 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -81.73562 ymin: -4.229406 xmax: -66.84722 ymax: 13.39473
Geodetic CRS: WGS 84
Simple feature collection with 1122 features and 11 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -81.73562 ymin: -4.229406 xmax: -66.84722 ymax: 13.39473
Geodetic CRS: WGS 84
First 10 features:
dpto_ccdgo mpio_ccdgo mpio_cdpmp dpto_cnmbr mpio_cnmbr mpio_crslc mpio_tipo
1 05 001 05001 ANTIOQUIA MEDELLÍN 1965 MUNICIPIO
2 05 002 05002 ANTIOQUIA ABEJORRAL 1814 MUNICIPIO
3 05 004 05004 ANTIOQUIA ABRIAQUÍ 1912 MUNICIPIO
4 05 021 05021 ANTIOQUIA ALEJANDRÍA Decreto departamental 304 de 1907 MUNICIPIO
5 05 030 05030 ANTIOQUIA AMAGÁ 1912 MUNICIPIO
6 05 031 05031 ANTIOQUIA AMALFI 1843 MUNICIPIO
7 05 034 05034 ANTIOQUIA ANDES 1853 MUNICIPIO
8 05 036 05036 ANTIOQUIA ANGELÓPOLIS Ordenanza 16 del 12 de julio de 1896 MUNICIPIO
9 05 038 05038 ANTIOQUIA ANGOSTURA 1821 MUNICIPIO
10 05 040 05040 ANTIOQUIA ANORÍ 1821 MUNICIPIO
mpio_narea mpio_nano shape_Leng shape_Area geom
1 374.74148 2025 1.0353795 0.030607649 MULTIPOLYGON (((-75.4857 6....
2 506.95978 2024 1.1585036 0.041383896 MULTIPOLYGON (((-75.46938 5...
3 296.97419 2025 0.8106670 0.024253315 MULTIPOLYGON (((-76.09047 6...
4 128.85643 2024 0.7051995 0.010534527 MULTIPOLYGON (((-75.0332 6....
5 84.11714 2024 0.4455330 0.006866507 MULTIPOLYGON (((-75.67587 6...
6 1208.34619 2025 2.0584824 0.098921100 MULTIPOLYGON (((-74.91364 7...
7 402.45060 2024 1.1469836 0.032816580 MULTIPOLYGON (((-75.86822 5...
8 81.86177 2024 0.4274956 0.006683387 MULTIPOLYGON (((-75.69149 6...
9 338.36185 2024 0.9164653 0.027679560 MULTIPOLYGON (((-75.27173 6...
10 1412.95696 2024 1.8476441 0.115706037 MULTIPOLYGON (((-74.90935 7...
para poder analizar los datos de la produccion de los frutales y los datos de los municipios haremos un join para eso los datos deben estar en el mismo formato
class(municipios$mpio_cdpmp)
[1] "character"
(stder.crs <- sf::st_crs(municipios))
Coordinate Reference System:
User input: WGS 84
wkt:
GEOGCRS["WGS 84",
ENSEMBLE["World Geodetic System 1984 ensemble",
MEMBER["World Geodetic System 1984 (Transit)"],
MEMBER["World Geodetic System 1984 (G730)"],
MEMBER["World Geodetic System 1984 (G873)"],
MEMBER["World Geodetic System 1984 (G1150)"],
MEMBER["World Geodetic System 1984 (G1674)"],
MEMBER["World Geodetic System 1984 (G1762)"],
MEMBER["World Geodetic System 1984 (G2139)"],
MEMBER["World Geodetic System 1984 (G2296)"],
ELLIPSOID["WGS 84",6378137,298.257223563,
LENGTHUNIT["metre",1]],
ENSEMBLEACCURACY[2.0]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433]],
CS[ellipsoidal,2],
AXIS["geodetic latitude (Lat)",north,
ORDER[1],
ANGLEUNIT["degree",0.0174532925199433]],
AXIS["geodetic longitude (Lon)",east,
ORDER[2],
ANGLEUNIT["degree",0.0174532925199433]],
USAGE[
SCOPE["Horizontal component of 3D system."],
AREA["World."],
BBOX[-90,-180,90,180]],
ID["EPSG",4326]]
vamos a añadir las vias de los municipios para ello descargamos los datos en un geoapackage de la siguiente pagina https://data.humdata.org/dataset/hotosm_col_roads, lo guerdaremos en el directorio de trabajo y usando la libreria sf filtraremos para obtener solo las vias de nuestro interes
list.files('/roads')
(sf.roads = st_read('roads.gpkg'))
Reading layer `roads' from data source
`C:\Users\Biblio\Desktop\proyecto 5-20261108T170448Z-1-001-20261111T154808Z-1-001\proyecto 5-20261108T170448Z-1-001\proyecto 5\entrega\roads.gpkg'
using driver `GPKG'
Simple feature collection with 1238606 features and 24 fields
Geometry type: GEOMETRY
Dimension: XY
Bounding box: xmin: -81.73539 ymin: -4.258755 xmax: -66.83066 ymax: 13.38636
Geodetic CRS: WGS 84
Simple feature collection with 1238606 features and 24 fields
Geometry type: GEOMETRY
Dimension: XY
Bounding box: xmin: -81.73539 ymin: -4.258755 xmax: -66.83066 ymax: 13.38636
Geodetic CRS: WGS 84
First 10 features:
id name name_en name_es highway surface smoothness width lanes oneway bridge layer
1 way/332900376 <NA> <NA> <NA> service <NA> <NA> <NA> <NA> <NA> <NA> <NA>
2 way/180388997 Carrera 17 <NA> <NA> residential unpaved <NA> <NA> <NA> <NA> <NA> <NA>
3 way/822292471 <NA> <NA> <NA> service unpaved <NA> 3 <NA> <NA> <NA> <NA>
4 way/835847133 Carrera 7 <NA> <NA> residential unpaved <NA> <NA> <NA> <NA> <NA> <NA>
5 way/76531894 Calle 24 <NA> <NA> residential unpaved <NA> <NA> <NA> yes <NA> <NA>
6 way/180781725 <NA> <NA> <NA> footway <NA> <NA> <NA> <NA> <NA> <NA> <NA>
7 way/180380289 Carrera 18 <NA> <NA> residential <NA> <NA> <NA> <NA> yes <NA> <NA>
8 way/574904069 Carrera 12 <NA> <NA> residential asphalt <NA> <NA> <NA> yes <NA> <NA>
9 way/1431563600 <NA> <NA> <NA> service <NA> <NA> <NA> <NA> <NA> <NA> <NA>
10 way/233980193 <NA> <NA> <NA> track <NA> <NA> <NA> <NA> <NA> <NA> <NA>
source adm0_pcode adm0_name adm1_pcode adm1_name adm2_pcode adm2_name adm3_pcode adm3_name adm4_pcode
1 <NA> COL Colombia CO81 Arauca CO81001 Arauca <NA> <NA> <NA>
2 <NA> COL Colombia CO81 Arauca CO81736 Saravena <NA> <NA> <NA>
3 <NA> COL Colombia CO81 Arauca CO81736 Saravena <NA> <NA> <NA>
4 <NA> COL Colombia CO81 Arauca CO81736 Saravena <NA> <NA> <NA>
5 <NA> COL Colombia CO81 Arauca CO81736 Saravena <NA> <NA> <NA>
6 <NA> COL Colombia CO81 Arauca CO81736 Saravena <NA> <NA> <NA>
7 <NA> COL Colombia CO81 Arauca CO81736 Saravena <NA> <NA> <NA>
8 <NA> COL Colombia CO81 Arauca CO81736 Saravena <NA> <NA> <NA>
9 <NA> COL Colombia CO81 Arauca CO81736 Saravena <NA> <NA> <NA>
10 <NA> COL Colombia CO81 Arauca CO81065 Arauquita <NA> <NA> <NA>
adm4_name name_latin geom
1 <NA> <NA> LINESTRING (-71.09269 6.957...
2 <NA> Carrera 17 LINESTRING (-71.87846 6.956...
3 <NA> <NA> LINESTRING (-71.83405 6.955...
4 <NA> Carrera 7 LINESTRING (-71.86707 6.955...
5 <NA> Calle 24 LINESTRING (-71.86982 6.957...
6 <NA> <NA> LINESTRING (-71.87532 6.956...
7 <NA> Carrera 18 LINESTRING (-71.87999 6.956...
8 <NA> Carrera 12 LINESTRING (-71.87189 6.955...
9 <NA> <NA> LINESTRING (-71.87497 6.956...
10 <NA> <NA> LINESTRING (-71.16664 6.963...
se pude obervar que estos vectores tipo de geometria LINESTRING es un tipo de geometría que representa una línea formada por una secuencia de puntos conectados (vértices). Es el tipo que se usa para elementos lineales son y hay 1.203.341 registros u objetos espaciales (organizados en 24 campos de atributos). por lo que vamos a filtrar solo en los datos que necessitamos
cambiamos los datos para que los municipios y las vias tengan el mismo CRS
nroads <- st_transform(sf.roads, crs= stder.crs)
aplicamos el filtro (el valor co05 varia de departamento en departamento)
(stder.roads.tmp = dplyr::filter(nroads, adm1_pcode=="CO05"))
Simple feature collection with 170634 features and 24 fields
Geometry type: GEOMETRY
Dimension: XY
Bounding box: xmin: -76.9709 ymin: 5.477896 xmax: -73.88851 ymax: 8.865483
Geodetic CRS: WGS 84
First 10 features:
id name name_en name_es highway surface smoothness width lanes oneway bridge
1 way/1284729480 <NA> <NA> <NA> track unpaved <NA> <NA> <NA> <NA> <NA>
2 way/251861484 <NA> <NA> <NA> track <NA> <NA> <NA> <NA> <NA> <NA>
3 way/251862287 <NA> <NA> <NA> residential <NA> <NA> <NA> <NA> <NA> <NA>
4 way/251862161 <NA> <NA> <NA> track <NA> <NA> <NA> <NA> <NA> <NA>
5 way/493380005 <NA> <NA> <NA> residential <NA> <NA> <NA> <NA> <NA> <NA>
6 way/493379972 <NA> <NA> <NA> residential <NA> <NA> <NA> <NA> <NA> <NA>
7 way/1495645394 <NA> <NA> <NA> track <NA> <NA> <NA> <NA> <NA> <NA>
8 way/1284729479 Norcasia-San Miguel <NA> <NA> unclassified gravel <NA> <NA> <NA> <NA> yes
9 way/251861268 <NA> <NA> <NA> track <NA> <NA> <NA> <NA> <NA> <NA>
10 way/251862288 <NA> <NA> <NA> track <NA> <NA> <NA> <NA> <NA> <NA>
layer source adm0_pcode adm0_name adm1_pcode adm1_name adm2_pcode adm2_name adm3_pcode adm3_name adm4_pcode
1 <NA> <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
2 <NA> <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
3 <NA> <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
4 <NA> <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
5 <NA> <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
6 <NA> <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
7 <NA> <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
8 1 <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
9 <NA> <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
10 <NA> <NA> COL Colombia CO05 Antioquia CO05756 Sonsón <NA> <NA> <NA>
adm4_name name_latin geom
1 <NA> <NA> LINESTRING (-74.76013 5.711...
2 <NA> <NA> LINESTRING (-74.78925 5.717...
3 <NA> <NA> LINESTRING (-74.81217 5.717...
4 <NA> <NA> LINESTRING (-74.81175 5.718...
5 <NA> <NA> LINESTRING (-74.81583 5.718...
6 <NA> <NA> LINESTRING (-74.81386 5.718...
7 <NA> <NA> LINESTRING (-74.79754 5.726...
8 <NA> Norcasia-San Miguel LINESTRING (-74.72984 5.725...
9 <NA> <NA> LINESTRING (-74.80196 5.729...
10 <NA> <NA> LINESTRING (-74.81869 5.738...
seleccionamos las columnas importantes
stder.roads.tmp %>% select('id', 'name', 'highway', 'adm2_pcode', 'adm2_name') -> stder.roads
tenemos que asegurararnos que los datos que vamos a unir sean del mismo tipo ademas vamos a usar la libreria janitor para ajustar y limpiar nuestros datos para que no ocurran errores ademas usamos stringr para los codigos de los municipios sean iguales, aplicamos filtros y realizamos el joint
library(janitor)
library(stringr)
# Limpiar nombres de columnas
frutales <- clean_names(frutales)
# Asegurar que el código DANE tenga 5 dígitos (agrega el 0 a la izquierda para Antioquia: "05XXX")
frutales <- frutales %>%
mutate(mpio_cdpmp = sprintf("%05d", as.numeric(codigo_dane_municipio)))
# Filtrar SOLO los municipios de Antioquia (cuyo código DANE inicia por "05")
municipios_antioquia <- municipios %>%
filter(startsWith(as.character(mpio_cdpmp), "05"))
# Realizar el join solo con los municipios de Antioquia
munic_frutales <- left_join(municipios_antioquia, frutales, by = "mpio_cdpmp")
munic_frutales <- munic_frutales %>%
mutate(etiqueta_mapa = ifelse(is.na(cultivo),
mpio_cnmbr,
paste0(mpio_cnmbr, "\n(", cultivo, ")")))
para crear el mapa debemos indicar las diferentes capas y objetos que vamos a utizar en nuestro mapa
frutales_map2 =
# CAPA 1: Municipios de Antioquia con Producción
tm_shape(munic_frutales) +
# Se quita tm_view para que encuadre automáticamente en Antioquia
tm_polygons(
fill = "produccion",
fill.scale = tm_scale_intervals(
style = "jenks",
n = 8),
fill.legend = tm_legend(title = "Producción (t)")
) +
tm_text(
text = "mpio_cnmbr",
size = 0.50,
fontfamily = "sans",
col = "#222222",
alpha = 0.85
) +
# CAPA 2: Vías de Antioquia
tm_shape(stder.roads) +
tm_lines(col = "darkgrey", lwd = 1.2, lty = "solid") +
# COMPONENTES DEL MAPA
tm_credits("Fuente: UPRA (2020)", fontface = "bold") +
tm_title("Producción de frutales en Antioquia (2020)",
fontface = "bold.italic",
fontfamily = "monospace") +
tm_scalebar(position = c("left", "bottom"))
── tmap v3 code detected ──────────────────────────────────────────────────────────
Ahora el mapa con el cultivo que hay en el departamento
frutales_map3 =
# CAPA 1: Municipios de Antioquia
tm_shape(munic_frutales) +
tm_polygons(
fill = "produccion",
fill.scale = tm_scale_intervals(
style = "jenks",
n = 8),
fill.legend = tm_legend(title = "Producción (t)")
) +
# ETIQUETAS: Muestra el nombre del municipio y el cultivo debajo
tm_text(
text = "cultivo", # Muestra la combinación de municipio y cultivo
size = 0.45, # Reducido ligeramente para evitar amontonamiento
fontfamily = "sans",
col = "#222222",
alpha = 0.85
) +
# CAPA 2: Vías
tm_shape(stder.roads) +
tm_lines(col = "darkgrey", lwd = 1.2, lty = "solid") +
# COMPONENTES DEL MAPA
tm_credits("Fuente: UPRA (2020)", fontface = "bold") +
tm_title("Cultivo principal y producción de frutales en Antioquia",
fontface = "bold.italic",
fontfamily = "monospace") +
tm_scalebar(position = c("left", "bottom"))
── tmap v3 code detected ───────────────────────────────────────────────────────────────────────────────────────────────────────────
ahoras visualisamos el mapa creado
frutales_map2
Aviso en graphics::strwidth(comp$text, units = "inch", family = comp$fontfamily, :
font family not found in Windows font database
[plot mode] fit legend/component: Some legend items or map compoments do not fit well, and are therefore
rescaled.
ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.
Aviso en grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
font family not found in Windows font database
frutales_map3
Aviso en graphics::strwidth(comp$text, units = "inch", family = comp$fontfamily, :
font family not found in Windows font database
[plot mode] fit legend/component: Some legend items or map compoments do not fit well, and are therefore rescaled.
ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.
Aviso en grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
font family not found in Windows font database
##7. Referencias
Lizarazo, I. 2026. How to make a map of agricultural production. Available at https:rpubs.com/ials2un/MakeEVAmap