1. Introducción

Este es el tercer Cuaderno R Markdown para el curso Geomática Básica 2026-2. Ilustra cómo obtener estadísticas multianuales para un grupo dado de cultivos en cualquier departamento. Usaremos como fuente principal de datos las Evaluaciones Agropecuarias Municipales (EVA), un conjunto de datos agropecuarios 2007-2018 proporcionado por el Ministerio de Agricultura y Desarrollo Rural. En mi caso, el análisis se hace para el departamento del Cesar.

2. Configuración

En este paso, instalaremos y cargaremos las librerías de R requeridas.

# ejecute las siguientes líneas desde la línea de comandos:
#install.packages('dplyr')
#install.packages('readxl')
#install.packages('sf')

knitr::opts_chunk$set(message = FALSE, warning = FALSE)
options(dplyr.summarise.inform = FALSE)

library(tidyverse)
library(dplyr)
library(readr)
library(ggplot2)

# función auxiliar: escribe los números con punto de miles
fmt <- function(x) format(round(x), big.mark = ".", decimal.mark = ",", scientific = FALSE)

3. Descargar el conjunto de datos EVA multianual para su departamento

Vaya a https://www.datos.gov.co/Agricultura-y-Desarrollo-Rural/Evaluaciones-Agropecuarias-Municipales-EVA/2pnw-mmge/data para encontrar el conjunto de datos. En el sitio enlazado (es decir, datos.gov.co), visualice los datos y aplique un filtro para obtener solo los datos correspondientes a su departamento. Luego, exporte los datos en formato csv. Ahora, vaya a la carpeta de descargas para encontrar el archivo Evaluaciones_Agropecuarias_Municipales_EVA.csv. Muévalo a su directorio de trabajo.

3. Leer el conjunto de datos EVA

list.files(".", pattern=c('csv'))
## [1] "Evaluaciones_Agropecuarias_Municipales_EVA_20261110.csv"

Ahora, procedamos a leer el conjunto de datos EVA:

# ajuste la ruta del archivo de acuerdo con sus datos
# (aquí el código busca solo el archivo CSV de EVA en la carpeta de trabajo)
archivo <- list.files(".", pattern = "^(CULTIVO_CESAR|Evaluaciones_Agropecuarias).*\\.csv$")[1]

# revisión: el archivo no debe tener bytes vacíos (archivo dañado)
bytes <- readBin(archivo, "raw", n = file.size(archivo))
if (sum(bytes == as.raw(0)) > 0) {
  stop("El archivo CSV está dañado (tiene bytes vacíos). Descárguelo de nuevo y cópielo a la carpeta del proyecto.")
}

# el archivo tiene encabezados con saltos de línea, así que se leen las líneas
# y se asignan los nombres de columna manualmente
lineas <- read_lines(archivo, locale = locale(encoding = "UTF-8"))
ini <- grep('^"?[0-9]+"?,"', lineas)[1]

nombres_eva <- c("CÓD. \nDEP.", "DEPARTAMENTO", "CÓD. MUN.", "MUNICIPIO",
                 "GRUPO \nDE CULTIVO", "SUBGRUPO \nDE CULTIVO", "CULTIVO",
                 "DESAGREGACIÓN REGIONAL Y/O SISTEMA PRODUCTIVO", "AÑO", "PERIODO",
                 "Área Sembrada\n(ha)", "Área Cosechada\n(ha)", "Producción\n(t)",
                 "Rendimiento\n(t/ha)", "ESTADO FISICO PRODUCCION",
                 "NOMBRE \nCIENTIFICO", "CICLO DE CULTIVO")

(eva <- read_csv(I(paste(lineas[ini:length(lineas)], collapse = "\n")),
                 col_names = nombres_eva,
                 col_types = cols(.default = col_character())))

Visualice la tabla y confirme que contiene estadísticas agropecuarias para diferentes años. ¿Puede decir cuál es el período de tiempo de estos datos?

Respuesta: los datos van del año 2006 al 2018. La tabla tiene 5.191 registros.

Es muy importante saber cuáles son los nombres que el software “ve”. Pueden ser diferentes de los que vemos nosotros. Averigüémoslo:

names(eva)
##  [1] "CÓD. \nDEP."                                  
##  [2] "DEPARTAMENTO"                                 
##  [3] "CÓD. MUN."                                    
##  [4] "MUNICIPIO"                                    
##  [5] "GRUPO \nDE CULTIVO"                           
##  [6] "SUBGRUPO \nDE CULTIVO"                        
##  [7] "CULTIVO"                                      
##  [8] "DESAGREGACIÓN REGIONAL Y/O SISTEMA PRODUCTIVO"
##  [9] "AÑO"                                          
## [10] "PERIODO"                                      
## [11] "Área Sembrada\n(ha)"                          
## [12] "Área Cosechada\n(ha)"                         
## [13] "Producción\n(t)"                              
## [14] "Rendimiento\n(t/ha)"                          
## [15] "ESTADO FISICO PRODUCCION"                     
## [16] "NOMBRE \nCIENTIFICO"                          
## [17] "CICLO DE CULTIVO"

4. Limpiar el conjunto de datos EVA

Seleccionemos algunos atributos para limpiar el objeto eva:

# revise la salida del chunk anterior y
# cambie los nombres de los atributos de acuerdo con sus propios datos
eva %>%
  dplyr::select('CÓD. MUN.':'ESTADO FISICO PRODUCCION') -> eva.tmp
eva.tmp

Revise la salida y verifique que solo se seleccionaron las columnas relevantes.

Respuesta: sí, quedaron solo las columnas que van desde el código del municipio hasta el estado físico de la producción.

Ahora, cambiemos los nombres de varias columnas que contienen caracteres vacíos o “ruidosos”:

eva.tmp %>%
  dplyr::rename('Cod_Mun' = 'CÓD. MUN.',
                'Grupo' = 'GRUPO \nDE CULTIVO',
                'Subgrupo' = 'SUBGRUPO \nDE CULTIVO',
                'Year' = 'AÑO',
                'AreaSembrada' = 'Área Sembrada\n(ha)',
                'AreaCosechada' = 'Área Cosechada\n(ha)',
                'Produccion' = 'Producción\n(t)',
                'Rendimiento' = 'Rendimiento\n(t/ha)',
                'Sistema' = 'DESAGREGACIÓN REGIONAL Y/O SISTEMA PRODUCTIVO',
                'Estado' = 'ESTADO FISICO PRODUCCION') -> new_eva

Revisemos la salida:

new_eva

Revise la tabla anterior y verifique que los atributos cuantitativos estén almacenados como tipos de datos numéricos (no como cadenas de texto).

Respuesta: en mi archivo esos atributos estaban como texto, porque los números vienen con formato colombiano (punto para los miles y coma para los decimales). Por eso los convertí a numéricos. Además, el archivo trae algunas filas de La Guajira, así que dejé solo las del Cesar:

new_eva <- new_eva %>%
  mutate(across(c(Year, AreaSembrada, AreaCosechada, Produccion, Rendimiento),
                ~ parse_number(as.character(.x), locale = locale(decimal_mark = ",", grouping_mark = "."))))

if ("DEPARTAMENTO" %in% names(new_eva)) {
  new_eva <- new_eva %>% filter(DEPARTAMENTO == "CESAR")
}

new_eva

Después de este paso quedan 5.191 registros del Cesar y los atributos cuantitativos ya son numéricos.

5. Análisis de datos

Muchas tareas de análisis de datos pueden abordarse usando el paradigma split-apply-combine (dividir-aplicar-combinar): dividir los datos en grupos, aplicar algún análisis a cada grupo y luego combinar los resultados. La librería dplyr hace esto muy fácil mediante el uso de la función group_by(), que divide los datos en grupos. Cuando los datos están agrupados de esta manera, summarize() puede usarse para colapsar cada grupo en un resumen de una sola fila. summarize() hace esto aplicando una función de agregación o resumen a cada grupo.

5.1 Los cultivos más importantes entre 2007 y 2018

Por ejemplo, si queremos averiguar la producción total por grupo de cultivos, escribimos:

new_eva %>%
  ##filter(Produccion > 0) %>%
  group_by(Grupo) %>%
  summarize(total_produccion = sum(Produccion)) %>%
  arrange(desc(total_produccion))

Note que la producción total contiene la suma de la producción de cada grupo de cultivos entre 2007 y 2018. En el Cesar, los dos cultivos con mayor producción fueron “OLEAGINOSAS” (2.043.635 t) y “CEREALES” (1.840.165 t).

Para guardar la producción total en un objeto:

new_eva %>%
  group_by(Grupo) %>%
  summarize(total_produccion = sum(Produccion)) -> PT

Para filtrar los cultivos más importantes:

PT %>%
  filter(total_produccion > 1000000) -> main.groups
main.groups

Para conocer la producción total de los principales grupos de cultivos:

(value = sum(main.groups$total_produccion))
## [1] 4995277

Para agregar un nuevo atributo con el porcentaje de la producción total:

main.groups$percent = main.groups$total_produccion/value
main.groups

Para crear un gráfico de torta de la producción total de main.groups:

library(ggplot2)
# Gráfico de barras
bp<- ggplot(main.groups, aes(x="", y=percent, fill=Grupo))+
  geom_bar(width = 1, stat = "identity")
# Gráfico de torta
pie <- bp + coord_polar("y", start=0)
pie

En la torta se ve que las oleaginosas son la mayor parte de lo que producen los tres grupos principales (40.9 %). Los cereales tienen 36.8 % y los tubérculos y plátanos 22.3 %.

5.2 Municipios con mayor producción para cada grupo de cultivos:

Para averiguar los municipios líderes en la producción de cada cultivo entre 2007 y 2018:

new_eva %>%
  group_by(Grupo, MUNICIPIO) %>%
  summarize(total_prod = sum(Produccion, na.rm = TRUE)) %>%
  slice(which.max(total_prod)) %>%
  arrange(desc(total_prod))

Para guardar el objeto:

new_eva %>%
  group_by(Grupo, MUNICIPIO) %>%
  summarize(total_prod = sum(Produccion, na.rm = TRUE)) %>%
  slice(which.max(total_prod)) -> leaders
leaders

Para filtrar los municipios más importantes desde el punto de vista agrícola:

leaders %>%
  filter(total_prod > 50000) -> main.leaders
main.leaders

Graficuemos los líderes filtrados:

# Gráfico de barras básico
p<-ggplot(data=main.leaders, aes(x=MUNICIPIO, y=total_prod)) +
  geom_bar(stat="identity") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
p

El municipio que más produce en un solo grupo es El Copey, con 410.045 t de oleaginosas. Cada grupo tiene un municipio líder distinto.

5.3 Dinámica de un cultivo importante entre 2007 y 2018

El cultivo y el municipio se escogen automáticamente: son los de mayor producción total en el Cesar.

top_mc <- new_eva %>%
  group_by(MUNICIPIO, CULTIVO) %>%
  summarize(total = sum(Produccion, na.rm = TRUE), .groups = "drop") %>%
  arrange(desc(total)) %>%
  slice(1)

new_eva %>%
  filter(MUNICIPIO == top_mc$MUNICIPIO & CULTIVO == top_mc$CULTIVO) %>%
  group_by(Year, CULTIVO) %>%
  select(MUNICIPIO, CULTIVO, Produccion, Year) -> cesar_cultivo

Revisemos la salida:

cesar_cultivo

Hagamos un gráfico rápido de la producción de palma de aceite en El Copey para todo el período de tiempo cubierto por el conjunto de datos EVA:

g <- ggplot(aes(x = Year, y = Produccion/1000), data = cesar_cultivo) +
  geom_bar(stat = 'identity') +
  labs(y = paste('Produccion de', str_to_title(top_mc$CULTIVO), '[Ton x 1000]'))

Agreguemos un título y visualicemos:

g + ggtitle(paste("Evolución de la Producción del Cultivo de", str_to_title(top_mc$CULTIVO),
                  "en", str_to_title(top_mc$MUNICIPIO), "de 2007 a 2018")) +
  labs(caption = "Basado en datos EVA (Minagricultura, 2020)")

El Copey produjo en total 410.045 toneladas de palma de aceite en el período, y en el gráfico se ve cómo fue cambiando la producción de un año a otro.

6. Análisis y gráficos adicionales

He ilustrado unos pocos ejemplos de análisis. Podría analizar otras variables distintas a producción (por ejemplo rendimiento, áreacosechada, áreasembrada). A continuación hago algunos análisis adicionales sobre el departamento del Cesar.

6.1 El cultivo que más se produce en el Cesar

El cultivo que más se produce en todo el departamento es la palma de aceite, con 2.043.585 toneladas. Eso es el 29.5 % de toda la producción registrada en el Cesar. Después vienen arroz (1.162.426 t) y yuca (703.132 t).

Figura: cultivo de palma de aceite

La palma de aceite es un cultivo permanente, es decir, una vez sembrada sigue produciendo durante muchos años. Veamos cómo cambió en todo el departamento:

new_eva %>%
  filter(CULTIVO == top_cultivo) %>%
  group_by(Year) %>%
  summarize(AreaSembrada = sum(AreaSembrada, na.rm = TRUE),
            Produccion = sum(Produccion, na.rm = TRUE)) -> palma_anual

palma_anual %>%
  pivot_longer(c(AreaSembrada, Produccion), names_to = "Variable", values_to = "Valor") %>%
  mutate(Variable = recode(Variable,
                           AreaSembrada = "Área sembrada [ha]",
                           Produccion = "Producción [t]")) %>%
  ggplot(aes(x = Year, y = Valor)) +
  geom_line() +
  geom_point() +
  facet_wrap(~Variable, scales = "free_y") +
  scale_x_continuous(breaks = seq(2007, 2018, 3)) +
  labs(x = "Año", y = "", title = "Palma de aceite en el Cesar: área sembrada y producción",
       caption = "Basado en datos EVA (Minagricultura, 2020)")

Entre 2007 y 2018 la producción de palma de aceite pasó de 117.922 a 249.741 toneladas, es decir, se multiplicó por 2.1. El área sembrada también creció, de 38.352 a 94.664 hectáreas. Parece que la producción subió sobre todo porque se sembró más área.

6.2 Municipios con mayor producción total en el Cesar

new_eva %>%
  group_by(MUNICIPIO) %>%
  summarize(total = sum(Produccion, na.rm = TRUE)) %>%
  arrange(desc(total)) %>%
  slice(1:10) -> top_mun

ggplot(top_mun, aes(x = reorder(str_to_title(MUNICIPIO), total), y = total/1000)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  labs(x = "Municipio", y = "Producción total [Ton x 1000]",
       title = "Los 10 municipios con mayor producción agrícola del Cesar",
       caption = "Basado en datos EVA (Minagricultura, 2020)")

Los municipios que más producen son Valledupar (689.518 t) y El Copey (681.890 t). Entre los diez primeros suman el 63.7 % de la producción del departamento.

6.3 Producción total del departamento por año

new_eva %>%
  filter(Year >= 2007) %>%
  group_by(Year) %>%
  summarize(total = sum(Produccion, na.rm = TRUE)) -> prod_anual

ggplot(prod_anual, aes(x = Year, y = total/1000)) +
  geom_line() +
  geom_point() +
  scale_x_continuous(breaks = 2007:2018) +
  labs(x = "Año", y = "Producción total [Ton x 1000]",
       title = "Producción agrícola total del Cesar por año",
       caption = "Basado en datos EVA (Minagricultura, 2020)")

La producción total del departamento está entre 471.076 y 639.521 toneladas por año. El año con más producción fue 2017 y el de menos fue 2010. El año 2006 no se incluyó en este gráfico porque en el archivo tiene muy pocos registros.

6.4 Conclusiones

En el Cesar la mayor parte de la producción agrícola viene de tres grupos: oleaginosas, cereales y tubérculos y plátanos. La palma de aceite es el cultivo que más se produce y creció bastante entre 2007 y 2018, sobre todo porque aumentó el área sembrada. La producción se concentra en pocos municipios, entre ellos Valledupar y El Copey, y cada grupo de cultivos tiene un municipio líder distinto.

7. Bibliografía

Lizarazo, I., 2022. Understanding dynamic productivity of crops. Disponible en https://rpubs.com/ials2un/production_dyn_v1.

Ministerio de Agricultura y Desarrollo Rural, 2020. Evaluaciones Agropecuarias Municipales (EVA). Datos Abiertos Colombia. https://www.datos.gov.co/Agricultura-y-Desarrollo-Rural/Evaluaciones-Agropecuarias-Municipales-EVA/2pnw-mmge/data

sessionInfo()
## R version 4.6.1 (2026-06-24 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 22000)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=Spanish_Colombia.utf8  LC_CTYPE=Spanish_Colombia.utf8   
## [3] LC_MONETARY=Spanish_Colombia.utf8 LC_NUMERIC=C                     
## [5] LC_TIME=Spanish_Colombia.utf8    
## 
## time zone: America/Bogota
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] lubridate_1.9.5 forcats_1.0.1   stringr_1.6.0   dplyr_1.2.1    
##  [5] purrr_1.2.2     readr_2.2.0     tidyr_1.3.2     tibble_3.3.1   
##  [9] ggplot2_4.0.3   tidyverse_2.0.0
## 
## loaded via a namespace (and not attached):
##  [1] bit_4.6.0          gtable_0.3.6       jsonlite_2.0.0     crayon_1.5.3      
##  [5] compiler_4.6.1     tidyselect_1.2.1   parallel_4.6.1     jquerylib_0.1.4   
##  [9] scales_1.4.0       yaml_2.3.12        fastmap_1.2.0      R6_2.6.1          
## [13] labeling_0.4.3     generics_0.1.4     knitr_1.52         bslib_0.12.0      
## [17] pillar_1.11.1      RColorBrewer_1.1-3 tzdb_0.5.0         rlang_1.3.0       
## [21] stringi_1.8.9      cachem_1.1.0       xfun_0.62          sass_0.4.10       
## [25] S7_0.2.2           bit64_4.8.6        otel_0.2.0         timechange_0.4.0  
## [29] cli_3.6.6          withr_3.0.3        magrittr_2.0.5     digest_0.6.39     
## [33] grid_4.6.1         vroom_1.7.1        rstudioapi_0.19.0  hms_1.1.4         
## [37] lifecycle_1.0.5    vctrs_0.7.3        evaluate_1.0.5     glue_1.8.1        
## [41] farver_2.1.2       rmarkdown_2.32     tools_4.6.1        pkgconfig_2.0.3   
## [45] htmltools_0.5.9