Análisis del estatuto de oposición 2021

Cargar librerías con funciones necesarias.

library(tidyverse)
library(patchwork)
library(ggplot2)
library(sf)
library(rnaturalearth)
library(rnaturalearthdata)
library(raster)
library(readxl)
library(fuzzyjoin)
library(stringdist)
library(ggthemes)
library(gridExtra)
library(stringi)
library(vtable)
library(cowplot)

Datos

Declaratorias de oposición

Del Consejo Nacional Electoral descargamos los datos de las organizaciones políticas que se han declarado en oposición para 2021 durante el gobierno de Iván Duque. Tiene información de cada partido a nivel municipal, en los Concejos; departamental, en las Asambleas; y nacional en el Congreso de la República. Según la Ley 1909 de 2018, los partidos tienen un mes luego del inicio del gobierno para decidir si se declaran en oposición, como independientes o como de gobierno.

Ganadores territoriales

Del Centro de Estudios en Democracia y Asuntos Electorales (CEDAE) podemos descargar los ganadores de las elecciones territoriales en 2019 para gobernaciones, asambleas, alcaldias y concejos.

Gobernaciones <- read.csv("C:/Users/tomas/OneDrive/Documents/UniAndes/Oposición/Ganadores/2019_gobernacion.dta.csv")

Asambleas <- read.csv("C:/Users/tomas/OneDrive/Documents/UniAndes/Oposición/Ganadores/2019_asamblea.dta.csv")

Alcaldías <- read.csv("C:/Users/tomas/OneDrive/Documents/UniAndes/Oposición/Ganadores/2019_alcaldia.dta.csv")

Concejos <- read.csv("C:/Users/tomas/OneDrive/Documents/UniAndes/Oposición/Ganadores/2019_concejo.dta.csv")

Cada partido, alianza y grupo ciudadano significativo (G.C.S.) tiene asignado un código en específico. Los códigos electorales están dentro de las bases de datos de asambleas y concejos sin nombres ni apellidos para cada movimiento político. Su codigo_lista es 0.

Cod_partidos_C <- Concejos %>% 
  filter(codigo_lista=="0") %>%
  distinct(nombres, codigo_partido)

Cod_partidos_A <- Asambleas %>% 
  filter(codigo_lista=="0") %>%
  distinct(nombres, codigo_partido)

Cod_partidos <- left_join(Cod_partidos_C, Cod_partidos_A,
                          by = join_by(codigo_partido, nombres))

Complementamos esta lista con el diccionario de partidos electorales del CEDAE. (https://cedae.datasketch.co/datos-democracia/resultados-electorales/descarga-los-datos/). Ambas bases con los nombres de los partidos tienen nomenclaturas distintas, por lo que se debe diferenciar entre ellas con el nombre de la columna. Se usa group_by() y slice() para dejar solo un nombre por cada código de partido.

Partidos <- read_excel("~/UniAndes/Oposición/Partidos_Electorales.xlsx")

Cod_partidos <- left_join(Partidos, Cod_partidos,
                          by = join_by(codigo_partido))

# Con el cambio de nombre queda claro que el primero es el nombre con el que el partido se presentó en la elección, mientras que el otro es descriptivo frente a la coalición y su extensión territorial.

Cod_partidos <- Cod_partidos %>%
  rename(nombre_movimiento = nombres,
         eleccion_movimiento = nombre_partido) %>%
  group_by(codigo_partido) %>%
  slice(1)

Ahora podemos depurar cada base de datos para que solo contenga a quienes ganaron las elecciones. distinct() colapsa la base de datos para que quede un movimiento político por observación.

#Para las gobernaciones dejamos al gobernador de cada departamento con su partido. 
Gobernaciones <- Gobernaciones %>% 
  subset(curules=="1") %>%
  group_by(departamento) %>%
  mutate(total_votos=sum(votos)) %>%
  distinct(id_electoral, coddpto, departamento, codigo_partido, primer_apellido, segundo_apellido, nombres, total_votos)

#Para las asambleas, se calcula los votos por partido en cada departamento, así como el total de curules de cada partido y el total de la Asamblea Departamental por voto popular. 

  Asambleas <- Asambleas %>%
    subset(curules=="1") %>%
    group_by(coddpto, codigo_partido) %>%
    mutate(total_votos = sum(votos)) %>%
    ungroup() %>%
    distinct(id_electoral, coddpto, departamento, codigo_partido, primer_apellido, segundo_apellido, nombres, total_votos, curules)
  
  Asambleas <- Asambleas %>% 
    group_by(coddpto, codigo_partido) %>%
    mutate(total_curules = sum(curules)) %>%
    ungroup() %>%
    group_by(coddpto) %>%
    mutate(curules_dpto = sum(curules)) %>%
    distinct(id_electoral, coddpto, departamento, codigo_partido, total_votos, total_curules, curules_dpto)

# En Alcaldías queda el alcalde de cada municipio.   
  
Alcaldías <- Alcaldías %>% 
  subset(curules=="1")

#Y finalmente, en Concejos queda nuevamente el número de curules por partido y el total de curules a repartir en cada Concejo Municipal. 

Concejos <- Concejos %>%
  subset(curules=="1") %>%
  group_by(codmpio, codigo_partido) %>%
  mutate(total_votos = sum(votos), 
         total_curules = sum(curules)) %>%
  ungroup() %>%
  group_by(codmpio) %>% 
  mutate(curules_mpio = sum(curules)) %>%
  distinct(id_electoral, coddpto, departamento, codmpio, municipio, codigo_partido, total_votos, total_curules, curules_mpio)

Luego debemos arreglar las bases de datos para que tanto la base de los Concejos como la de Oposición sean compatibles y se pueda hacer la unión según sus partidos con la base de las declaratorias. Todos los nombres quedarán sin tildes y sin símbolos como ", - o ..

Cod_partidos <- Cod_partidos %>%
  mutate(
    nombre_movimiento = sub("MOVIMIENTO AUTORIDADES INDIGENAS DE COLOMBIA  AICO", "Movimiento Autoridades Indígenas De Colombia Aico", nombre_movimiento),
    eleccion_movimiento = sub("PARTIDO CENTRO DEMOCRATICO  MANO FIRME CORAZON GRANDE", "PARTIDO CENTRO DEMOCRATICO", eleccion_movimiento),
    nombre_movimiento = gsub('["-.]', '', nombre_movimiento),
    eleccion_movimiento = gsub('["-.]', '', eleccion_movimiento)
  )

Oposicion <- Oposicion %>%
  mutate_at(
    vars(agp_nombre, mcp_nombre, dpt_nombre),
    ~ gsub('["-.]', '', .) %>%
      iconv("UTF-8", "ASCII//TRANSLIT"))

Por último, agregamos a las bases de datos el nombre de los partidos con nuestra lista de códigos de partidos.

Gobernaciones <- left_join(Gobernaciones, Cod_partidos,
                           by = join_by("codigo_partido"))

Asambleas <- left_join(Asambleas, Cod_partidos,
                           by = join_by("codigo_partido"))

Alcaldías <- left_join(Alcaldías, Cod_partidos,
                           by = join_by("codigo_partido"))

Concejos <- left_join(Concejos, Cod_partidos,
                           by = join_by("codigo_partido"))

Para el caso de los Concejos y las Asambleas, se puede calcular finalmente el porcentaje de curules que tiene cada partido o movimiento en cada municipio y departamento.

Concejos <- Concejos %>% mutate(pct_curules = (total_curules / curules_mpio) *100)
  
Asambleas <- Asambleas %>% mutate(pct_curules = (total_curules / curules_dpto) *100)

Análisis nacional

Ahora trabajamos con la base de datos de declaratorias de oposición de la Registraduría. Tenemos la columna de dcl_nivel_terrotirial con la escala territorial de la declaratoria del partido. Comenzamos por hacer el análisis de los partidos en el congreso y sus declaratorias a nivel nacional. Para cada escala territorial se hace un gráfico de barras y de pastel.

# Sub conjunto de partidos por su declaración vigente con el porcentaje. 

dcl_nacional <- Oposicion %>% 
  filter(dcl_vigente=="1") %>%
  subset(dcl_nivel_territorial == "Nacional") %>% 
  group_by(lst_descripcion) %>% 
  summarise(total = n()) %>% 
  mutate(porcentaje = total/sum(total) * 100)

bar_nacional <- ggplot(dcl_nacional, aes(x = reorder(lst_descripcion, -total), y = total)) +
  geom_bar(stat = "identity", aes(fill = lst_descripcion), 
           show.legend = F) +
  geom_text(aes(label = total), vjust = -0.5) +
  labs(x = "Partidos Políticos", y = "Cantidad", title = "Cantidad de Declaratorias de Partidos Políticos") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

pie_nacional <- ggplot(dcl_nacional, aes(x = "", y = total, fill = lst_descripcion)) +
  geom_bar(stat = "identity", width = 1) +
  geom_text(aes(label = paste0(round(porcentaje), "%")), position = position_stack(vjust = 0.5)) +
  coord_polar("y", start = 0) +
  labs(fill = "Partidos Políticos", title = "Proporción de Declaratorias de Partidos Políticos") +
  theme_minimal() +
  theme(axis.text = element_blank(),
        axis.title = element_blank(),
        legend.position = "right")

bar_nacional + pie_nacional

En 2021, había 16 partidos con personería jurídica ante el Consejo Nacional Electoral, de los cuáles el 38% (6 partidos) se declararon como de gobierno a nivel Nacional, 31% (5 partidos) se declararon como de oposición, y el otro 31% (5) restante se declararon como partidos independientes frente al gobierno nacional de Iván Duque.

Análisis Departamental

A nivel departamental, los 16 partidos se declaran de gobierno, de oposición o independientes frente a los 32 gobiernos departamentales en 2021. Hay 217 declaraciones vigentes, en promedio 6.7 por departamento.

dcl_departamental <- Oposicion %>% 
  filter(dcl_vigente=="1") %>%
  subset(dcl_nivel_territorial == "Departamental") %>% 
  group_by(lst_descripcion) %>% 
  summarise(total = n()) %>% 
  mutate(porcentaje = total/sum(total) * 100)

bar_departamental <- ggplot(dcl_departamental, aes(x = reorder(lst_descripcion, -total), y = total)) +
  geom_bar(stat = "identity", aes(fill = lst_descripcion), 
           show.legend = F) +
  geom_text(aes(label = total), vjust = -0.5) +
  labs(x = "Partidos Políticos", y = "Cantidad", title = "Cantidad de Declaratorias de Partidos Políticos") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

pie_departamental <- ggplot(dcl_departamental, aes(x = "", y = total, fill = lst_descripcion)) +
  geom_bar(stat = "identity", width = 1) +
  geom_text(aes(label = paste0(round(porcentaje), "%")), position = position_stack(vjust = 0.5)) +
  coord_polar("y", start = 0) +
  labs(fill = "Partidos Políticos", title = "Proporción de Declaratorias de Partidos Políticos") +
  theme_minimal() +
  theme(axis.text = element_blank(),
        axis.title = element_blank(),
        legend.position = "right")

bar_departamental + pie_departamental

Frente a los gobiernos departamentales, el 57% (123) partidos se delcararon como de gobierno, un 30% (66 partidos) como independientes y tan solo el 13% restante (28 partidos) se delcararon de oposición.

Promedios departamentales

En cada departamento es distinta la distribución de como se agrupan los partidos. Es por esto que para saber el porcentaje promedio de partidos en cada una de las categorías para cada departamento, debemos calcular agrupando por categoría territorial.

Lo primero que debemos hacer es crear un subconjunto de datos con las declaraciones departamentales y vigentes. Además dividimos la variable lst_descripcion en tres variables binomiales para cada categoría.

Departamentos <- Oposicion %>%
  filter(dcl_nivel_territorial=="Departamental" & dcl_vigente=="1") %>%
  mutate(es_gobierno = ifelse(lst_descripcion=="Gobierno", 1, 0),
         es_independiente = ifelse(lst_descripcion=="Independiente", 1,0), 
         es_oposicion = ifelse(lst_descripcion=="Oposición",1,0))

Luego, a partir de esta nueva base de datos, calculamos la suma de partidos en cada departamento, así como la suma de cada una de las categorías por departamento. Agrupamos por departamento y calculamos.

Avg_departamentos <- Departamentos %>%
  group_by(dcl_departamento_dpt_codigo, dpt_nombre) %>%
  summarise(sum_partidos = n(),
            sum_gobierno = sum(es_gobierno),
            sum_independinetes = sum(es_independiente),
            sum_oposicion = sum(es_oposicion))

Ahora que tenemos la suma poro categoría y el total de partidos por departamento, podemos calcular cada porcentaje en la misma base de datos.

Avg_departamentos <- Avg_departamentos %>%
  mutate(pct_gobierno = sum_gobierno/sum_partidos*100, 
         pct_independientes = sum_independinetes/sum_partidos*100, 
         pct_oposicion = sum_oposicion/sum_partidos*100)

Finalmente podemos calcular el promedio de los porcentajes de cada departamento.

Avg_departamentos %>% sumtable(vars = c("pct_gobierno",
                                        "pct_independientes",
                                        "pct_oposicion"),
                               summ = c("mean(x)",
                                        "max(x)",
                                        "min(x)",
                                        "sd(x)"),
                               factor.numeric = T,
                               digits = 3,
                               labels = c("Porcentaje de partidos de gobierno",
                                          "Porcentaje de partidos independientes",
                                          "Porcentaje de partidos de oposición"),
                               title = "Estadísticas de las declaratorias departamentales")
Estadísticas de las declaratorias departamentales
Variable Mean Max Min Sd
Porcentaje de partidos de gobierno 56.9 100 0 24.5
Porcentaje de partidos independientes 31.4 100 0 24.5
Porcentaje de partidos de oposición 11.7 30 0 11.3

Además de ver que la diferencia con los promedios generales de los partidos no es mucha, también observamos que en el departamento que tiene mayor porcentaje de partidos en oposición, este número tan solo llega al 30%. La desviación estándar es mucho menor para las declaratorias de oposición.

Análisis Municipal

Hay 1.123 municipios en Colombia. Cada municipio tiene un número de partidos distinto con declaratorias vigentes de oposición, gobierno o independencia.

dcl_municipal <- Oposicion %>% 
  filter(dcl_vigente=="1") %>%
  subset(dcl_nivel_territorial == "Municipal") %>% 
  group_by(lst_descripcion) %>% 
  summarise(total = n()) %>% 
  mutate(porcentaje = total/sum(total) * 100)

bar_municipal <- ggplot(dcl_municipal, aes(x = reorder(lst_descripcion, -total), y = total)) +
  geom_bar(stat = "identity", aes(fill = lst_descripcion), 
           show.legend = F) +
  geom_text(aes(label = total), vjust = -0.5) +
  labs(x = "Partidos Políticos", y = "Cantidad", title = "Cantidad de Declaratorias de Partidos Políticos") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

pie_municipal <- ggplot(dcl_municipal, aes(x = "", y = total, fill = lst_descripcion)) +
  geom_bar(stat = "identity", width = 1) +
  geom_text(aes(label = paste0(round(porcentaje), "%")), position = position_stack(vjust = 0.5)) +
  coord_polar("y", start = 0) +
  labs(fill = "Partidos Políticos", title = "Proporción de Declaratorias de Partidos Políticos") +
  theme_minimal() +
  theme(axis.text = element_blank(),
        axis.title = element_blank(),
        legend.position = "right")

bar_municipal + pie_municipal

La tendencia creciente de partidos de gobierno se refuerza, al igual que la disminución de partidos de oposición en una base mucho más grande.

Promedios municipales

Ahora vamos a ver el promedio de partidos declarados en oposición para cada uno de los municipios, y sacar el ponderado de esos promedios.

# Filtrar para quedarnos solo con las declaraciones a nivel municipal y vigentes. También creamos tres nuevas variables para las categorías de oposición según el Estatuto. 

Municipios <- Oposicion %>%
  filter(dcl_nivel_territorial == "Municipal" & dcl_vigente == 1) %>%
   mutate(es_gobierno = if_else(lst_descripcion == "Gobierno", 1, 0),
         es_oposicion = if_else(lst_descripcion == "Oposición", 1, 0),
         es_independiente = if_else(lst_descripcion == "Independiente", 1, 0))

# Agrupar por municipio y sumar las variables de categorías y el total de partidos.



Avg_municipios <- Municipios %>%
  group_by(dpt_nombre, dcl_municipio_mcp_codigo, mcp_nombre) %>%
  summarise(sum_gobierno = sum(es_gobierno),
            sum_oposicion = sum(es_oposicion),
            sum_independiente = sum(es_independiente),
            sum_partidos = n())

# Calcular los porcentajes de cada categoría en cada municipio
Avg_municipios <- Avg_municipios %>%
  mutate(pct_gobierno = (sum_gobierno / sum_partidos) * 100,
         pct_oposicion = (sum_oposicion / sum_partidos) * 100,
         pct_independiente = (sum_independiente / sum_partidos) * 100)

# Calcular los promedios generales de los porcentajes para todos los municipios en Colombia

Avg_municipios %>% sumtable(vars = c("pct_gobierno",
                                        "pct_independiente",
                                        "pct_oposicion"),
                               summ = c("mean(x)",
                                        "max(x)",
                                        "min(x)",
                                        "sd(x)"),
                               factor.numeric = T,
                               digits = 3,
                               labels = c("Porcentaje de partidos de gobierno",
                                          "Porcentaje de partidos independientes",
                                          "Porcentaje de partidos de oposición"),
                               title = "Estadísticas de las declaratorias municipales")
Estadísticas de las declaratorias municipales
Variable Mean Max Min Sd
Porcentaje de partidos de gobierno 52.6 100 0 20.1
Porcentaje de partidos independientes 37.3 100 0 22.6
Porcentaje de partidos de oposición 10.1 75 0 15.2

Nuevamente no hay mucha diferencia con los promedios generales. Para la escala municipal se disminuye la diferencia entre las desviaciones estándar y vemos que el máximo para el porcentaje de partidos en oposición aumenta a 75%. Los mínimos son 0 para todas las categorías de declaratoria.

Partidos ganadores en cada territorio

Con la lista de partidos y la lista de ganadores en gobernaciones, asambleas, alcaldías y concejos, podemos examinar la combinación de partidos políticos, Grupos Significativos Ciudadanos y coaliciones electorales que fueron electas.

Variables

Para esto usamos el directorio de partidos del CEDAE que en eleccion_movimiento divide a los movimientos por “Partido”, “G.S.C” y “Coalición”. Haremos tres nuevas columnas para crear variables binomiales en gobernaciones y alcaldías.

Gobernaciones <- Gobernaciones %>% 
  mutate(es_GSC = ifelse(str_detect(eleccion_movimiento, "GSC"), 1, 0),
         es_coalicion = ifelse(str_detect(eleccion_movimiento, "COALICION"), 1, 0),
         es_partido = ifelse(str_detect(eleccion_movimiento, "^PARTIDO"), 1, 0))

Alcaldías <- Alcaldías %>%
  mutate(es_GSC = ifelse(str_detect(eleccion_movimiento, "GSC"), 1, 0),
         es_coalicion = ifelse(str_detect(eleccion_movimiento, "COALICION"), 1, 0),
         es_partido = ifelse(str_detect(eleccion_movimiento, "^PARTIDO"), 1, 0))

Proporciones de gobernaciones y alcaldías

Ahora vamos a ver la proporción de partidos, GSC y coaliciones que ganaron alcaldías y gobernaciones.

sum(Gobernaciones$es_GSC == 1)/nrow(Gobernaciones)
## [1] 0.03125
sum(Gobernaciones$es_partido == 1)/nrow(Gobernaciones)
## [1] 0.1875
sum(Gobernaciones$es_coalicion == 1)/nrow(Gobernaciones)
## [1] 0.78125
sum(Alcaldías$es_GSC == 1)/nrow(Alcaldías)
## [1] 0.02363636
sum(Alcaldías$es_partido == 1)/nrow(Alcaldías)
## [1] 0.4763636
sum(Alcaldías$es_coalicion == 1)/nrow(Alcaldías)
## [1] 0.46

Vemos que para la escala departamental el tipo de movimiento más exitoso son las coaliciones, con un 78.1% de las gobernaciones elegidas. Por otro lado, para las alcaldías hay la misma representantividad entre los partidos (47.6%) y las coaliciones (46%).

En ambas escalas los Grupos Significativos Ciudadanos no llegan al superar al 4% de las gobernaciones y alcaldías elegidas.

Proporciones Concejos y Asambleas

En el caso de los Concejos Municipales y las Asambleas Departamentales, contamos con la cantidad de curules de cada entidad territoriales y las curules de cada partido, GSC y coalición. Según el Estatuto de la Oposición, solo los partidos políticos con personería jurídica deben declararse en oposición, de gobierno o como independientes. Podemos aislar estos datos para calcular la proporción de los concejales y diputados en cada categoría.

En primer lugar, creamos las variables en la base de datos de Concejos para aislar a los partidos con personería jurídica. A partir de ahí podemos hacer la unión de las bases de datos entre los partidos en los concejos y sus declaratorias a nivel municipal.

Concejos <- Concejos %>% 
  mutate(tipo_movimiento = 
           ifelse(str_detect(eleccion_movimiento, "GSC"), "GSC", 
         ifelse(str_detect(eleccion_movimiento, "COALICION"), "Coalición", 
         ifelse(str_detect(eleccion_movimiento, "^PARTIDO"), "Partido", "Partido"))))

Concejos_curules <- stringdist_left_join(Concejos,
  subset(Oposicion, dcl_nivel_territorial == "Municipal" & dcl_vigente == 1),
  by = c("nombre_movimiento" = "agp_nombre", "codmpio" = "dcl_municipio_mcp_codigo"),
  max_dist = 0.9,
  method = "dl",
  ignore_case = TRUE, 
)

Con cada una de las declaratorias y el número de partidos en los Concejos podemos agrupar por municipio para analizar la proporción de partidos de gobierno, independientes y de oposición en cada Concejo.

#Agrupa por municipio y crea variables que suman la cantidad de veces que dice la declaratora, que no es NA, entre los distintos partidos en cada Concejo

Concejos_curules <- Concejos_curules %>%
  ungroup() %>%
  group_by(codmpio) %>%
  mutate(pct_agp_gobierno = sum(lst_descripcion == "Gobierno" &
                              !is.na(lst_descripcion)) 
         / sum(n_distinct(eleccion_movimiento)) * 100,
         pct_agp_oposicion = sum(lst_descripcion == "Oposición" &
                              !is.na(lst_descripcion)) 
         / sum(n_distinct(eleccion_movimiento)) * 100,
         pct_agp_independiente = sum(lst_descripcion == "Independiente" &
                              !is.na(lst_descripcion)) 
         / sum(n_distinct(eleccion_movimiento)) * 100, 
         pct_agp_NA = sum(is.na(lst_descripcion)) 
         / sum(n_distinct(eleccion_movimiento)) * 100)

También se puede hacer un proceso similar con el número de curules que tiene cada partido de cada categoría, y dividir entre el total de curules por municipio. Así vemos la representatividad que tiene cada categoría del Estatuto de la Oposición el cada Concejo.

Concejos_curules <- Concejos_curules %>%
  group_by(codmpio) %>%
  mutate(pct_cur_gobierno = sum(total_curules[lst_descripcion == "Gobierno" & !is.na(lst_descripcion)]) / curules_mpio*100,
         pct_cur_oposicion = sum(total_curules[lst_descripcion == "Oposición" & !is.na(lst_descripcion)]) / curules_mpio*100,
         pct_cur_independiente = sum(total_curules[lst_descripcion == "Independiente" & !is.na(lst_descripcion)]) / curules_mpio*100, 
         pct_cur_NA = sum(total_curules[is.na(lst_descripcion)]) / curules_mpio*100)

Ahora podemos repetir el mismo proceso para las Asambleas departamentales. Debido a que en la base de Asambleas hay algunos partidos en donde no hay un nombre del movimiento registrado en la base de datos, convertimos esos NA a espacios en blanco para poder hacer la unión.

Asambleas$nombre_movimiento[is.na(Asambleas$nombre_movimiento)] <- ""

Asambleas_curules <- stringdist_left_join(Asambleas,
  subset(Oposicion, dcl_nivel_territorial == "Departamental" & dcl_vigente == 1),
  by = c("nombre_movimiento" = "agp_nombre", "coddpto" = "dcl_departamento_dpt_codigo"),
  max_dist = 0.9,
  method = "dl",
  ignore_case = TRUE
)

Asambleas$nombre_movimiento[Asambleas$nombre_movimiento == ""] <- NA

Asambleas_curules$nombre_movimiento[Asambleas_curules$nombre_movimiento == ""] <- NA


Asambleas_curules <- Asambleas_curules %>%
  ungroup() %>%
  group_by(coddpto) %>%
  mutate(pct_agp_gobierno = sum(lst_descripcion == "Gobierno" &
                              !is.na(lst_descripcion)) 
         / sum(n_distinct(eleccion_movimiento)) * 100,
         pct_agp_oposicion = sum(lst_descripcion == "Oposición" &
                              !is.na(lst_descripcion)) 
         / sum(n_distinct(eleccion_movimiento)) * 100,
         pct_agp_independiente = sum(lst_descripcion == "Independiente" &
                              !is.na(lst_descripcion)) 
         / sum(n_distinct(eleccion_movimiento)) * 100, 
         pct_agp_NA = sum(is.na(lst_descripcion)) 
         / sum(n_distinct(eleccion_movimiento)) * 100)

Asambleas_curules <- Asambleas_curules %>%
  group_by(coddpto) %>%
  mutate(pct_cur_gobierno = sum(total_curules[lst_descripcion == "Gobierno" & !is.na(lst_descripcion)]) / curules_dpto*100,
         pct_cur_oposicion = sum(total_curules[lst_descripcion == "Oposición" & !is.na(lst_descripcion)]) / curules_dpto*100,
         pct_cur_independiente = sum(total_curules[lst_descripcion == "Independiente" & !is.na(lst_descripcion)]) / curules_dpto*100, 
         pct_cur_NA = sum(total_curules[is.na(lst_descripcion)]) / curules_dpto*100)

Análisis estadístico de Asambleas y Concejos

A continuación, producimos con la librería de vtable, una tabla con las estadísticas de los porcentajes de partidos y curules en cada categoría del Estatuto de la Oposición para los Concejos Municipales. De la misma forma, hacemos con las Asambleas Departamentales.

Concejos_curules %>% 
  group_by(departamento, municipio, codmpio) %>% 
  st(vars = c("pct_agp_gobierno", 
              "pct_agp_oposicion", 
              "pct_agp_independiente", 
              "pct_agp_NA",
            "pct_cur_gobierno", 
            "pct_cur_oposicion", 
            "pct_cur_independiente",
            "pct_cur_NA"),
   col.breaks = 4, 
   summ = c("mean(x)",
            "max(x)",
            "min(x)", 
            "sd(x)"),
   factor.numeric = T,
   digits = 3,
   labels = c("Porcentaje de partidos de gobierno",
              "Porcentaje de partidos de oposicion",
              "Porcentaje de partidos independientes",
              "Porcentaje de partidos sin declaratoria",
              "Porcentaje de curules de gobierno",
              "Porcentaje de curules de oposicion",
              "Porcentaje de curules independientes",
              "Porcentaje de curules sin declaratoria"),
   title = "Declaratorias del Estatuto de la Oposicion en Concejos Municipales")
Declaratorias del Estatuto de la Oposicion en Concejos Municipales
Variable Mean Max Min Sd Variable Mean Max Min Sd
Porcentaje de partidos de gobierno 40.8 100 0 19.1 Porcentaje de curules de gobierno 45.1 100 0 20.5
Porcentaje de partidos de oposicion 7.04 66.7 0 11.7 Porcentaje de curules de oposicion 7.21 66.7 0 12.4
Porcentaje de partidos independientes 29.1 100 0 19.1 Porcentaje de curules independientes 28.3 100 0 19.7
Porcentaje de partidos sin declaratoria 23.1 100 0 17.1 Porcentaje de curules sin declaratoria 19.4 100 0 16.3

Para los Concejos Municipales, vemos que la categoría más común para los partidos es declararse de gobierno (40.8%), lo que se traduce en un 45.1% de las curules promedio en los concejos. Luego siguen los partidos declarados como independientes con un 28.3% de representación en los concejos, y finalmente, los partidos de oposición que son los menos comúnes con tan solo un 7% y una representación del 7.2%.

Como los GSC y las coaliciones no deben emitir una declaratoria según el Estatuto de la Oposición, hay un 23.1% de movimientos sin declaratoria y esto representa el 19.4% de las curules en promedio.

Con los máximos podemos ver que no hay ningún concejo municipal que tenga el 100% de las curules de oposición, pero sí hay concejos que se componen por completo de partidos de gobierno, independientes e incluso sin declaratoria. La desviación estándar es menor también para la oposición, lo que indica que suele ser bajo el porcentaje en la mayoría de los concejos.

Asambleas_curules %>% 
  group_by(departamento, coddpto) %>% 
  st(vars = c("pct_agp_gobierno", 
              "pct_agp_oposicion", 
              "pct_agp_independiente", 
              "pct_agp_NA",
            "pct_cur_gobierno", 
            "pct_cur_oposicion", 
            "pct_cur_independiente",
            "pct_cur_NA"),
   col.breaks = 4, 
   summ = c("mean(x)",
            "max(x)",
            "min(x)", 
            "sd(x)"),
   factor.numeric = T,
   digits = 3,
   labels = c("Porcentaje de partidos de gobierno",
              "Porcentaje de partidos de oposicion",
              "Porcentaje de partidos independientes",
              "Porcentaje de partidos sin declaratoria",
              "Porcentaje de curules de gobierno",
              "Porcentaje de curules de oposicion",
              "Porcentaje de curules independientes",
              "Porcentaje de curules sin declaratoria"),
   title = "Declaratorias del Estatuto de la Oposicion en Asambleas Departamentales")
Declaratorias del Estatuto de la Oposicion en Asambleas Departamentales
Variable Mean Max Min Sd Variable Mean Max Min Sd
Porcentaje de partidos de gobierno 43.4 100 11.1 21 Porcentaje de curules de gobierno 46.5 100 10 23.2
Porcentaje de partidos de oposicion 7.31 28.6 0 8.5 Porcentaje de curules de oposicion 7.11 38.5 0 8.97
Porcentaje de partidos independientes 20.5 57.1 0 17.5 Porcentaje de curules independientes 24.7 70 0 21
Porcentaje de partidos sin declaratoria 28.8 60 0 13.9 Porcentaje de curules sin declaratoria 21.8 50 0 13.3

Las estadísticas departamentales mantienen la misma tendencia de muchos partidos de gobierno y pocos de oposición. En esta escala se invierten los papeles de los partidos independientes y los movimientos sin declaratoria, pues hay un 28.8% en promedio que no definen su postura ante el Estatuto de la Oposición, y representan el 21.4% de los diputados departamentales.

Para las asambleas también cambian los máximos y los mínimos, pues la única categoría con un máximo de 100% es la de gobierno, así como la única que no llega a un mínimo de 0%: en todas las asambleas hay diputados de gobierno. La desviación estándar es aún más baja para la oposición, que indica una mayor proporción de departamentos con porcentajes muy bajos de partidos en oposición.

Cartografía ganadores

En un mapa podemos analizar la distribución de las categorías de ganadores en las elecciones territoriales. Para esto, las tres categorías deben estar ahora en la misma variable.

Gobernaciones <- Gobernaciones %>%
  mutate(tipo_movimiento = 
           ifelse(str_detect(eleccion_movimiento, "GSC"), "GSC", 
         ifelse(str_detect(eleccion_movimiento, "COALICION"), "Coalición", 
         ifelse(str_detect(eleccion_movimiento, "^PARTIDO"), "Partido", "Partido"))))

Alcaldías <- Alcaldías %>% 
  mutate(tipo_movimiento = 
           ifelse(str_detect(eleccion_movimiento, "GSC"), "GSC", 
         ifelse(str_detect(eleccion_movimiento, "COALICION"), "Coalición", 
         ifelse(str_detect(eleccion_movimiento, "^PARTIDO"), "Partido", "Partido"))))

De internet podemos extraer la base de datos georreferenciada con los departamentos y municipios de Colombia. Primero se debe estandarizar la convención para eliminar símbolos y tildes, y luego hacemos la unión con la base de datos de Gobernaciones.

mapa_dpto <- getData(name = "GADM", country = "COL", level = 1)

mapa_dpto <- st_as_sf(mapa_dpto)

mapa_dpto <- mapa_dpto %>%
  mutate_at(
    vars(NAME_0, NAME_1, VARNAME_1),
    ~ gsub('["-.]', '', .) %>%
      iconv("UTF-8", "ASCII//TRANSLIT")) %>%
   mutate(NAME_1 = sub("San Andres y Providencia", "ARCHIPIELAGO DE SAN ANDRES PROVIDENCIA Y SANTA CATALINA", NAME_1))

mapa_ganadores_dpto <- stringdist_left_join(mapa_dpto, Gobernaciones,
                                            by = c("NAME_1" = "departamento"),
                                            max_dist = 0.9,
                                            ignore_case = T)
ggplot(mapa_ganadores_dpto) +
  geom_sf(aes(fill = tipo_movimiento, geometry = geometry)) +
  labs(title = "Movimientos políticos electos para las gobernaciones en 2019") + 
  theme_map() + 
  labs(fill = "Tipo de movimiento") +
  theme_minimal() 

Ahora podemos visualizar la predominancia de los gobernadores que ganan por coaliciones de varios partidos y movimientos políticos. De igual forma vemos que el único gobernado de un Grupo Significativo Ciudadano es aquel del Magdalena. Todos los candidatos de las regiones Andina y Pacífica ganan mediante coaliciones.

Seguimos con la cartografía municipal. Para este caso debemos modificar varios nombres de municipios que no se correlacionan con la base de datos del CEDAE. Tras identificar los municipios y cambiar sus nombres, podemos generar la unión y el mapa.

mapa_mcp <- getData(name = "GADM", country = "COL", level = 2)

mapa_mcp <- st_as_sf(mapa_mcp)

mapa_mcp <- mapa_mcp %>%
  mutate_at(
    vars(NAME_0, NAME_1, NAME_2, VARNAME_2),
    ~ gsub('["-.]', '', .) %>%
      iconv("UTF-8", "ASCII//TRANSLIT")) %>%
    mutate(
    NAME_1 = case_when(
      NAME_1 == "San Andres y Providencia" ~ "ARCHIPIELAGO DE SAN ANDRES PROVIDENCIA Y SANTA CATALINA",
      NAME_2 == "Santafe de Bogota" & NAME_1 == "Cundinamarca" ~ "BOGOTA DC", 
      TRUE ~ NAME_1),
    NAME_2 = case_when(
      NAME_2 == "Santiago de Cali" ~ "CALI",
      NAME_2 == "Santafe de Bogota" ~ "BOGOTA DC",
      NAME_2 == "La Union de Sucre" ~ "LA UNION",
      NAME_2 == "Tolu" ~ "SANTIAGO DE TOLU",
      NAME_2 == "Toluviejo" ~ "SAN JOSE DE TOLUVIEJO",
      NAME_2 == "Since" ~ "SAN LUIS DE SINCE",
      NAME_2 == "San Antonio de Palmito" ~ "PALMITO",
      NAME_1 != "Antioquia" & NAME_2 == "San Andres" ~ "SAN ANDRES",
      NAME_2 == "Carolina del Principe" ~ "CAROLINA",
      NAME_2 == "Don Matias" ~ "DONMATIAS",
      NAME_2 == "San Vicente" ~ "SAN VICENTE FERRER",
      NAME_2 == "San Estanislao de Kostka" ~ "SAN ESTANISLAO",
      NAME_2 == "Guican" ~ "GUICAN DE LA SIERRA",
      NAME_1 == "Antioquia" & NAME_2 == "Bolivar" ~ "CIUDAD BOLIVAR",
      NAME_2 == "Mompos" ~ "SANTA CRUZ DE MOMPOX",
      NAME_2 == "Piendamo" ~ "PIENDAMO  TUNIA",
      NAME_2 == "Sotara" ~ "SOTARA PAISPAMBA",
      NAME_1 == "Cesar" & NAME_2 == "Manaure" ~ "MANAURE BALCON DEL CESAR",
      NAME_2 == "Purisima" ~ "PURISIMA DE LA CONCEPCION",
      NAME_2 == "Santa Cruz de Lorica" ~ "LORICA",
      NAME_2 == "San Bernardino de Sahagun" ~ "SAHAGUN",
      NAME_2 == "San Juan de Rio Seco" ~ "SAN JUAN DE RIOSECO",
      NAME_2 == "Puerto Inirida" ~ "INIRIDA",
      NAME_2 == "Santa Marta Dist Esp" ~ "SANTA MARTA",
      NAME_2 == "Pueblo Viejo" ~ "PUEBLOVIEJO",
      NAME_2 == "La Uribe" ~ "URIBE",
      NAME_2 == "Vista Hermosa" ~ "VISTAHERMOSA",
      NAME_2 == "San Luis de Cubarral" ~ "CUBARRAL",
      NAME_2 == "San Juan de Pasto" ~ "PASTO",
      NAME_2 == "Tumaco" ~ "SAN ANDRES DE TUMACO",
      NAME_2 == "Santa Cruz" ~ "SANTACRUZ",
      NAME_2 == "Cuaspud" ~ "CUASPUD CARLOSAMA",
      NAME_2 == "La Playa de Belen" ~ "LA PLAYA",
      NAME_2 == "Salazar de las Palmas" ~ "SALAZAR",
      NAME_2 == "Santo Domingo de Silos" ~ "SILOS",
      NAME_2 == "San Miguel de Mocoa" ~ "MOCOA",
      TRUE ~ NAME_2
    )
  )

# Combinar datos geoespaciales con información de declaratorias

mapa_ganadores_mcp <- stringdist_left_join(mapa_mcp, Alcaldías, 
                                     by = c("NAME_1" = "departamento", "NAME_2" = "municipio"),
                                     max_dist = 0.9, 
                                     method = "lv",
                                     ignore_case = TRUE)

ggplot(mapa_ganadores_mcp) +
  geom_sf(aes(fill = tipo_movimiento, geometry = geometry)) +
  labs(title = "Movimientos políticos electos para las alcaldías en 2019") +
  theme_map() + 
  labs(fill = "Tipo de movimiento") +
  theme_minimal() 

Las regiones que vemos en gris son corregimientos o áreas no municipalizadas por su población o su falta de centros poblacionales y cascos urbanos.

La región Andina nuevamente concentra a los alcaldes que ganan por coalición, especialmente sobre los municipios de cordillera oriental y el piedemonte llanero. En la región de la Orinoquía, el Caribe y el Pacífico vemos que aumentan los alcaldes que quedaron elegidos con solo un partido político y con personería jurídica. Los casos de Grupos Significativos Ciudadanos no presentan un patrón geográfico claro.

Análisis territorial

A continuación, podemos hacer el análsis cartográfico de las declaratorias de oposición y las distintas categorías del Estatuto de la Oposición en cada departamento y municipio.

Análisis departamental

Hacemos la unión con el promedio de declaratorias de gobierno a nivel departamental y se crea una escala según el porcentaje de partidos de gobierno en cada departamento.

# Combinar datos geoespaciales con información de declaratorias
mapa_dcl_dpto <- stringdist_left_join(mapa_dpto, Avg_departamentos, 
                                      by = c("NAME_1" = "dpt_nombre"),
                       max_dist = 1, 
                       ignore_case = T) 

# Crear mapa electoral coloreando los departamentos según la cantidad de declaratorias
mapa_gobierno_dpto <- ggplot(mapa_dcl_dpto) +
  geom_sf(aes(fill = pct_gobierno, geometry = geometry)) +
  labs(title = "Declaratorias de Partidos Políticos de Gobierno por Departamento") + 
  theme_map() +
  scale_fill_gradient(low = "white", high = "#08306b", 
                                  guide = guide_colorbar(reverse = TRUE)) + 
  labs(fill = "Porcentaje de Gobierno") +
  theme_minimal() 

# Mostrar mapa electoral
mapa_gobierno_dpto

Ahora podemos repetir el proceso para declaraciones de independencia y de oposición en la misma escala.

# Independientes

mapa_independientes_dpto <- ggplot(mapa_dcl_dpto) +
  geom_sf(aes(fill = pct_independientes, geometry = geometry)) +
  labs(title = "Declaratorias de Partidos Políticos en Independencia por Departamento") + 
  theme_map() +
  scale_fill_gradient(low = "#f7fbff", high = "darkorange", 
                                  guide = guide_colorbar(reverse = TRUE)) + 
  labs(fill = "Porcentaje de Independinetes") +
  theme_minimal() 

# Mostrar mapa electoral
mapa_independientes_dpto

# Oposición
mapa_oposicion_dpto <- ggplot(mapa_dcl_dpto) +
  geom_sf(aes(fill = pct_oposicion, geometry = geometry)) +
  labs(title = "Declaratorias de Partidos Políticos de Oposición por Departamento") + 
  theme_map() +
  scale_fill_gradient(low = "#f7fbff", high = "darkred", 
                                  guide = guide_colorbar(reverse = TRUE)) + 
  labs(fill = "Porcentaje de Oposición") +
  theme_minimal() 

# Mostrar mapa electoral
mapa_oposicion_dpto

Análisis Municipal

Avg_municipios <- stringdist_left_join(Alcaldías, Avg_municipios,
                                       by = c("codmpio" = "dcl_municipio_mcp_codigo"),
                                       method = "lv",
                                       max_dist = 0.9,
                                       ignore_case = TRUE)


# Realizar el join con la columna combinada
mapa_dcl_mcp <- stringdist_left_join(mapa_mcp, Avg_municipios, 
                                     by = c("NAME_2" = "municipio", "NAME_1" = "departamento"),
                                     max_dist = 1, 
                                     method = "lcs",
                                     ignore_case = TRUE)

# Crear mapa electoral coloreando los departamentos según la cantidad de declaratorias
mapa_gobierno_mcp <- ggplot(mapa_dcl_mcp) +
  geom_sf(aes(fill = pct_gobierno, geometry = geometry)) +
  labs(title = "Declaratorias de Partidos Políticos de Gobierno por Municipio") + 
  theme_map() +
  scale_fill_gradient(low = "#f7fbff", high = "#08306b", 
                                  guide = guide_colorbar(reverse = TRUE)) + 
  labs(fill = "Porcentaje de Gobierno") +
  theme_minimal() 

# Mostrar mapa electoral
mapa_gobierno_mcp

mapa_independientes_mcp <- ggplot(mapa_dcl_mcp) +
  geom_sf(aes(fill = pct_independiente, geometry = geometry)) +
  labs(title = "Declaratorias de Partidos Políticos en Independencia por Municipio") + 
  theme_map() +
  scale_fill_gradient(low = "#f7fbff", high = "orange", 
                                  guide = guide_colorbar(reverse = TRUE)) + 
  labs(fill = "Porcentaje de Independientes") +
  theme_minimal() 

# Mostrar mapa electoral
mapa_independientes_mcp

mapa_oposicion_mcp <- ggplot(mapa_dcl_mcp) +
  geom_sf(aes(fill = pct_oposicion, geometry = geometry)) +
  labs(title = "Declaratorias de Partidos Políticos de Oposición por Municipio") + 
  theme_map() +
  scale_fill_gradient(low = "#f7fbff", high = "red", 
                                  guide = guide_colorbar(reverse = TRUE)) + 
  labs(fill = "Porcentaje de Oposición") +
  theme_minimal() 

8# Mostrar mapa electoral
## [1] 8
mapa_oposicion_mcp

Podemos hacer la comparación de los 6 mapas al ponerlos en una grilla que compare escalas territoriales y categorías de oposición.

Grid_maps <- grid.arrange(mapa_gobierno_dpto,
                          mapa_independientes_dpto,
                          mapa_oposicion_dpto, 
                          mapa_gobierno_mcp, 
                          mapa_independientes_mcp, 
                          mapa_oposicion_mcp, 
                          ncol = 3)

ggsave(plot = Grid_maps, "mapas_oposición.pdf", 
       width = 20, height = 12)

Ensayo mapa San Andrés

Para mejorar la escala del departamento de San Andrés, Providencia y Santa Catalina, se puede ubicar en una escala mayor arriba a la izquierda del mapa de Colombia.

# Filtrar las filas correspondientes al Archipiélago de San Andrés y Providencia
archipielago <- subset(mapa_dcl_mcp, NAME_2 == "ARCHIPIELAGO DE SAN ANDRES PROVIDENCIA Y SANTA CATALINA")

# Crear mapa electoral coloreando los departamentos según la cantidad de declaratorias
mapa_gobierno_sa <- ggplot() +
  geom_sf(data = mapa_dcl_mcp, aes(fill = pct_gobierno, geometry = geometry)) +
  geom_sf(data = archipielago, fill = "white", color = "black", size = 1) + 
  theme_map() +
  scale_fill_gradient(low = "#f7fbff", high = "#08306b", 
                      guide = guide_colorbar(reverse = TRUE)) +
  labs(labs = NULL) +
  theme_minimal() +
  coord_sf(xlim = c(-81.8, -81.3), ylim = c(12.4, 13.5))  # Ajustar la extensión del mapa para enfocarse en el Archipiélago

# Mostrar mapa electoral
mapa_gobierno_sa

plot_grid(mapa_gobierno_sa, mapa_gobierno_mcp, ncol = 2, align = "hv")

mapa_gobierno_mcp + 
  annotation_custom(ggplotGrob(mapa_gobierno_sa), xmin = -82.5, xmax = -79.8, ymin = 11.7, ymax = 14.0)