Análisis electoral en Colombia (2018-2022)

Librería tidyverse para manejo de datos.

library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.2.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.0     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.1     ✔ tibble    3.1.8
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors

Importamos la base de datos:

Elecciones <- read.csv("C:\\Users\\tomas\\OneDrive\\Desktop\\ArcGIS\\UniAndes\\VOT_BOG_GEO.csv")

str(Elecciones)
## 'data.frame':    104666 obs. of  27 variables:
##  $ depto              : int  16 16 16 16 16 16 16 16 16 16 ...
##  $ depto_municipio    : chr  "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." ...
##  $ comuna             : chr  "1 USAQUÉN" "1 USAQUÉN" "1 USAQUÉN" "1 USAQUÉN" ...
##  $ zona               : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ eleccion           : chr  "Alcaldia 2019" "Alcaldia 2019" "Alcaldia 2019" "Alcaldia 2019" ...
##  $ cod_eleccion       : int  3 3 3 3 3 3 3 3 3 3 ...
##  $ codpuesto          : chr  "22" "22" "22" "22" ...
##  $ grupuesto          : int  22 22 22 22 22 22 22 28 28 28 ...
##  $ puesto             : chr  "ALESSANDRO VOLTA" "ALESSANDRO VOLTA" "ALESSANDRO VOLTA" "ALESSANDRO VOLTA" ...
##  $ posicion           : chr  "CENTRO" "CENTRO" "IZQUIERDA" "DERECHA" ...
##  $ codpetro           : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ candidato_o_partido: chr  "CARLOS FERNANDO GALAN PACHON" "CLAUDIA NAYIBE LOPEZ HERNANDEZ" "HOLLMAN MORRIS" "MIGUEL URIBE TURBAY" ...
##  $ v_can_pp_ele       : int  1056 645 112 434 61 8 6 630 692 190 ...
##  $ porc_v_can_pp_ele  : num  45.48 27.78 4.82 18.69 2.63 ...
##  $ tot_v_pp_ele       : int  2322 2322 2322 2322 2322 2322 2322 1894 1894 1894 ...
##  $ v_can_pp           : int  1056 645 112 434 756 79 57 630 692 190 ...
##  $ porc_v_can_pp      : num  4.238 2.588 0.449 1.742 3.034 ...
##  $ tot_v_pp           : int  24918 24918 24918 24918 24918 24918 24918 19488 19488 19488 ...
##  $ v_can_zona_ele     : int  105245 75455 13733 45830 8145 899 1266 105245 75455 13733 ...
##  $ porc_v_can_zona_ele: num  42 30.11 5.48 18.29 3.25 ...
##  $ tot_v_zona_ele     : int  250573 250573 250573 250573 250573 250573 250573 250573 250573 250573 ...
##  $ v_can_zona         : int  105245 75455 13733 45830 94181 10266 11341 105245 75455 13733 ...
##  $ porc_v_can_zona    : num  4.346 3.116 0.567 1.892 3.889 ...
##  $ tot_v_zona         : int  2421742 2421742 2421742 2421742 2421742 2421742 2421742 2421742 2421742 2421742 ...
##  $ direccion          : chr  "CALLE 119 # 4-79" "CALLE 119 # 4-79" "CALLE 119 # 4-79" "CALLE 119 # 4-79" ...
##  $ POINT_X            : num  -74 -74 -74 -74 -74 ...
##  $ POINT_Y            : num  4.69 4.69 4.69 4.69 4.69 ...
summary(Elecciones)
##      depto    depto_municipio       comuna               zona      
##  Min.   :16   Length:104666      Length:104666      Min.   : 1.00  
##  1st Qu.:16   Class :character   Class :character   1st Qu.: 7.00  
##  Median :16   Mode  :character   Mode  :character   Median :10.00  
##  Mean   :16                                         Mean   :10.22  
##  3rd Qu.:16                                         3rd Qu.:13.00  
##  Max.   :16                                         Max.   :98.00  
##                                                                    
##    eleccion          cod_eleccion    codpuesto           grupuesto    
##  Length:104666      Min.   :1.000   Length:104666      Min.   :  1.0  
##  Class :character   1st Qu.:4.000   Class :character   1st Qu.:230.0  
##  Mode  :character   Median :6.000   Mode  :character   Median :442.0  
##                     Mean   :5.623                      Mean   :444.3  
##                     3rd Qu.:7.000                      3rd Qu.:667.0  
##                     Max.   :9.000                      Max.   :898.0  
##                                                        NA's   :1709   
##     puesto            posicion            codpetro       candidato_o_partido
##  Length:104666      Length:104666      Min.   :0.00000   Length:104666      
##  Class :character   Class :character   1st Qu.:0.00000   Class :character   
##  Mode  :character   Mode  :character   Median :0.00000   Mode  :character   
##                                        Mean   :0.02936                      
##                                        3rd Qu.:0.00000                      
##                                        Max.   :1.00000                      
##                                                                             
##   v_can_pp_ele     porc_v_can_pp_ele  tot_v_pp_ele      v_can_pp       
##  Min.   :    1.0   Min.   : 0.0030   Min.   :   13   Min.   :     1.0  
##  1st Qu.:    4.0   1st Qu.: 0.1812   1st Qu.: 1408   1st Qu.:     6.0  
##  Median :   31.0   Median : 1.9684   Median : 3474   Median :    78.0  
##  Mean   :  289.3   Mean   : 6.9844   Mean   : 4141   Mean   :   764.3  
##  3rd Qu.:  215.8   3rd Qu.: 6.9242   3rd Qu.: 5941   3rd Qu.:   573.0  
##  Max.   :47119.0   Max.   :98.8971   Max.   :95018   Max.   :138420.0  
##                                                                        
##  porc_v_can_pp         tot_v_pp      v_can_zona_ele   porc_v_can_zona_ele
##  Min.   : 0.00022   Min.   :    25   Min.   :     1   Min.   : 0.00042   
##  1st Qu.: 0.03080   1st Qu.: 12065   1st Qu.:   277   1st Qu.: 0.17350   
##  Median : 0.53064   Median : 33083   Median :  3434   Median : 2.17057   
##  Mean   : 2.22350   Mean   : 38729   Mean   : 16557   Mean   : 6.95938   
##  3rd Qu.: 2.37803   3rd Qu.: 56555   3rd Qu.: 14972   3rd Qu.: 6.97578   
##  Max.   :70.99768   Max.   :458474   Max.   :299349   Max.   :82.60870   
##                                                                          
##  tot_v_zona_ele     v_can_zona     porc_v_can_zona      tot_v_zona     
##  Min.   :   366   Min.   :     1   Min.   : 0.00004   Min.   :   5327  
##  1st Qu.:114412   1st Qu.:   493   1st Qu.: 0.02614   1st Qu.:1196281  
##  Median :198233   Median :  8915   Median : 0.57936   Median :2054084  
##  Mean   :227859   Mean   : 44346   Mean   : 2.07733   Mean   :2184563  
##  3rd Qu.:355499   3rd Qu.: 39766   3rd Qu.: 2.43619   3rd Qu.:3377184  
##  Max.   :562680   Max.   :930456   Max.   :36.54965   Max.   :4317729  
##                                                                        
##   direccion            POINT_X          POINT_Y     
##  Length:104666      Min.   :-74.36   Min.   :3.986  
##  Class :character   1st Qu.:-74.14   1st Qu.:4.584  
##  Mode  :character   Median :-74.11   Median :4.622  
##                     Mean   :-74.11   Mean   :4.631  
##                     3rd Qu.:-74.08   3rd Qu.:4.683  
##                     Max.   :-74.02   Max.   :4.819  
##                     NA's   :1967     NA's   :1967

Distribuión de votos en el espectro electoral cronológicamente

Análisis de cómo se distribuyen los votos entre las distintas posiciones ideológicas en Colombia dentro de la variabale //posiciones//. Para ello primiero hay que ordenar la variable cronológicamente.

eleccion_orden <- c("Presi 1 v 2018", "Presi 2 v 2018", "Alcaldia 2019", "Concejo 2019", "JAL 2019", "Camara 2022", "Senado 2022", "Presi 1 v 2022", "Presi 2 v 2022")


Elecciones$eleccion <- factor(Elecciones$eleccion, levels = eleccion_orden)

Gráfica de barras con las elecciones como eje x y la distribución de votos como eje y en donde se muestre el cambio acumulado de las posiciones ideológicas entre cada elección.

ggplot(Elecciones, aes(x = eleccion, y = v_can_pp_ele, fill = posicion)) +
     geom_bar(stat = "identity", position = "fill") +
    scale_fill_manual(values = c("darkblue", "darkgreen", "red", "purple", "yellow", "brown","gray"),
                       labels = c("DERECHA", "CENTRO", "INDEPENDIENTE", "IZQUIERDA", 
                                  "MINORIA", "TRADICIONAL", "N/V")) +
     labs(x = "Elecciones en Colombia", y = "Distribución de votos", 
          title = "Cambio en la distribución de votos en el espectro político Colombiano",
          fill = "Posición política") +
     theme_bw(base_size = 16) +
     theme(plot.title = element_text(face = "bold", hjust = 0.5),
           legend.title = element_text(face = "bold"),
           legend.text = element_text(face = "italic"),
           legend.position = "bottom",
           axis.title.x = element_text(face = "bold"),
           axis.title.y = element_text(face = "bold"),
           panel.grid.major = element_blank(),
           panel.grid.minor = element_blank(),
           panel.background = element_blank())

Este gráfico de barras explica cómo va a cambiando la distribución de cada elección, pero al apilar las posiciones se pierde la capacidad de comparar los porcentajes de votos y hacer seguimiento a cada posición en partícular. Para esto se puede hacer un gráfico de línea con cada posición.

Primero se debe crear una nueva tabla que resuma los votos de cada posición en cada una de las elecciones. Cada posición debe ser tratada como una variable categórica. Se agrupan los datos de los puestos por elección y por posición política para sumar los votos de cada posición y crear una nueva variable con su porcentaje.

Elecciones$eleccion <- as.factor(Elecciones$eleccion)

eleccion_posicion <- Elecciones %>%
    group_by(eleccion, posicion) %>%
    summarize(votos = sum(v_can_pp_ele),
              porcentaje = sum(v_can_pp_ele) / sum(tot_v_pp_ele) * 100)
## `summarise()` has grouped output by 'eleccion'. You can override using the
## `.groups` argument.

Ahora se puede graficar el cambio del porcentaje de votos por posición en cada una de las elecciones. Se define a elección para el eje “x”, y porcentaje para el eje “y”. Para dividir por posición se le asigna el color. A continuación, se utiliza geom_line para graficar las líneas de cada posición política, utilizando aes(group = posicion) para indicar que se deben conectar las observaciones correspondientes a cada posición. El argumento linewidth se utiliza para aumentar el grosor de las líneas.

ggplot(eleccion_posicion, aes(x = eleccion, y = porcentaje, color = posicion)) +
    geom_line(aes(group = posicion), linewidth = 1.2) +
    scale_color_manual(values = c("darkblue", "darkgreen", "red", "purple", "yellow", "brown", "gray")) +
    labs(x = "Elecciones en Colombia y Bogotá", y = "Porcentaje de votos", 
         title = "Evolución de la preferencia política en Bogotá",
         color = "Posición política") +
    theme_bw(base_size = 16) +
    theme(plot.title = element_text(face = "bold", hjust = 0.5),
          legend.title = element_text(face = "bold"),
          legend.text = element_text(face = "italic"),
          legend.position = "bottom",
          axis.title.x = element_text(face = "bold"),
          axis.title.y = element_text(face = "bold"),
          panel.grid.major = element_blank(),
          panel.grid.minor = element_blank(),
          panel.background = element_blank())

Cambio en el porcentaje de cada partido para cada localidad

Para dividir los datos por las localidades, volvemos a agrupar la base de datos principal por cada elección y por las elecciones, pero esta vez también por la variable comuna que indica la localidad. Se crean dos nuevas variables con los votos totales de cada localidad y el porcentaje de cada posición en la localidad.

eleccion_comuna_posicion <- Elecciones %>%
    group_by(eleccion, comuna, posicion) %>%
    summarize(votos = sum(v_can_zona_ele),
              porcentaje = sum(v_can_zona_ele) / sum(tot_v_zona_ele) * 100)
## `summarise()` has grouped output by 'eleccion', 'comuna'. You can override
## using the `.groups` argument.

Con esta nueva base de datos se puede realizar la misma gráfica que anteriormente, pero incluyendo el componente de facet_wrap(~comuna) para que haga una gráfica por cada localidad. El tamaño de la fuente es más pequeño para poder ver las 20 localidades.

ggplot(eleccion_comuna_posicion, aes(x = eleccion, y = porcentaje, color = posicion)) +
  geom_line(aes(group = posicion), linewidth = 1.2) +
  scale_color_manual(values = c("darkblue", "darkgreen", "red", "purple", "yellow", "brown", "gray"), 
                     labels = c("DERECHA", "CENTRO", "INDEPENDIENTE", "IZQUIERDA", "MINORIA", "TRADICIONAL", "N/V")) +
  labs(x = "Elecciones en Colombia", y = "Porcentaje de votos", 
       title = "Evolución de la preferencia política en Bogotá por localidad",
       color = "Posición política") +
  facet_wrap(~comuna, ncol = 4) + 
  theme_bw(base_size = 8)  +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        legend.title = element_text(face = "bold"),
        legend.text = element_text(face = "italic"),
        legend.position = "bottom",
        legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
        axis.title.x = element_text(face = "bold"),
        axis.title.y = element_text(face = "bold"))

Análisis de las elecciones territoriales de 2019 para concejales en cada localidad.

Para ver el comportamiento de cada localidad en las elecciones territoriales creamos una nueva base de datos que contenga la información de las elecciones, las localidades y los candidatos. Así como calculamos, el total de votos para cada candidato en la localidad y el porcentaje de votos en cada localidad.

Agrupamos los datos por cada elección, las localidads y los distintos partidos. Luego creamos una variable con el total de los votos en cada localidad, y su porcentaje. Finalmente, eliminamos los datos repetidos.

eleccion_comuna_partido <- Elecciones %>%
  group_by(eleccion, comuna, candidato_o_partido) %>%
  reframe(total_votos = sum(v_can_zona_ele), 
            porc_votos = sum(v_can_zona_ele)/sum(tot_v_zona_ele)*100) %>%
  distinct() %>%
  view()

A continuación vamos a filtrar solo los datos para la elección del Concejo de 2019 y eliminamos la suma de todos los candidatos para que queden los partidos.

Can_localidad_concejo <- eleccion_comuna_partido %>%
 subset(eleccion == "Concejo 2019" & candidato_o_partido != "CANDIDATOS TOTALES")
summary(Can_localidad_concejo)
##            eleccion      comuna          candidato_o_partido  total_votos     
##  Concejo 2019  :320   Length:320         Length:320          Min.   :      1  
##  Presi 1 v 2018:  0   Class :character   Class :character    1st Qu.:  25472  
##  Presi 2 v 2018:  0   Mode  :character   Mode  :character    Median : 112074  
##  Alcaldia 2019 :  0                                          Mean   : 422703  
##  JAL 2019      :  0                                          3rd Qu.: 382514  
##  Camara 2022   :  0                                          Max.   :8146350  
##  (Other)       :  0                                                           
##    porc_votos      
##  Min.   : 0.03719  
##  1st Qu.: 0.73824  
##  Median : 3.01495  
##  Mean   : 4.77214  
##  3rd Qu.: 6.93415  
##  Max.   :26.86111  
## 

Hacemos una gráfica de barras con el total de votos de cada partido en cada localidad. El eje y es libre en cada gráfica para comparar mejor a las localidades independientemente del número de votos.

ggplot(Can_localidad_concejo, aes(x=candidato_o_partido, y=total_votos, fill=candidato_o_partido)) +
  geom_bar(stat = "identity") +
  scale_x_discrete(NULL, labels = NULL) +
  labs(title = "Votación por partidos en las elecciones al Concejo 2019 por localidad", 
       fill= "Partidos políticos", x=NULL, y="Total de votos por partido") +
  facet_wrap(~comuna, scales = "free_y")+
  theme_bw(base_size = 8)  +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        legend.title = element_text(face = "bold"),
        legend.text = element_text(face = "italic"),
        legend.position = "bottom",
        legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
        axis.title.x = element_text(face = "bold"),
        axis.title.y = element_text(face = "bold"))

Repetimos la gráfica mostrando el contraste en el número de votos de cada localidad con un eje y fijo.

ggplot(Can_localidad_concejo, aes(x=candidato_o_partido, y=total_votos, fill=candidato_o_partido)) +
  geom_bar(stat = "identity") +
  scale_x_discrete(NULL, labels = NULL) +
  labs(title = "Votación por partidos en las elecciones al Concejo 2019 por localidad", 
       fill= "Partidos políticos", x=NULL, y="Total de votos por partido") +
  facet_wrap(~comuna)+
  theme_bw(base_size = 8)  +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        legend.title = element_text(face = "bold"),
        legend.text = element_text(face = "italic"),
        legend.position = "bottom",
        legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
        axis.title.x = element_text(face = "bold"),
        axis.title.y = element_text(face = "bold"))

Para definir los 3 partidos más votados en cada localidad, ordenamos la base de datos de manera descendiente por el total de votos de cada partido y la agrupamos por localidad. Con la función slice() podemos sacar los 3 primero partidos de cada localidad. Para luego cartografiar los resultados, creamos una nueva base solo con el partido más votado de cada localidad, separamos la variable comuna en el código de la localidad y su nombre, así como cambiamos los nombres de las localidades para que queden igual a la base del shape.

Partidos_Concejo <- Can_localidad_concejo %>% arrange(desc(total_votos)) %>% group_by(comuna) %>% slice(1)

Partidos_Concejo <- separate(Partidos_Concejo, comuna, into = c("CodLoca", "Loca"), sep = " ", remove = FALSE, extra = "merge")

Partidos_Concejo$Loca <- sub("USAQUÉN", "USAQUEN", Partidos_Concejo$Loca)

Partidos_Concejo$Loca <- sub("URIBE", "URIBE URIBE", Partidos_Concejo$Loca)

Partidos_Concejo$Loca <- sub("MÁRTIRES", "LOS MARTIRES", Partidos_Concejo$Loca)


write.csv2(Partidos_Concejo, 
           file = "C:\\Users\\tomas\\OneDrive\\Desktop\\ArcGIS\\UniAndes\\Partidos_Concejo.csv")

view(Partidos_Concejo)

Comparación con Ediles por localidad en 2019

Repetimos el proceso para ver los candidatos más votados en las elecciones a la JAL 2019. Debido a que la coalición Colombia Humana se lanzó con nombres diferentes en todas las localidades, usamos el código sub() para reempazarlos por un solo nombre.

library(stringr)

Can_localidad_JAL <- eleccion_comuna_partido %>%
  subset(eleccion == "JAL 2019" & candidato_o_partido != "CANDIDATOS TOTALES")

Can_localidad_JAL$candidato_o_partido = sub(".*HUMANA.*", "COALICIÓN COLOMBIA HUMANA", Can_localidad_JAL$candidato_o_partido)

view(Can_localidad_JAL)

ggplot(Can_localidad_JAL, aes(x=candidato_o_partido, y=total_votos, fill=candidato_o_partido)) +
  geom_bar(stat = "identity") +
  scale_x_discrete(NULL, labels = NULL) +
  labs(title = "Votación por partidos en las elecciones al Concejo 2019 por localidad", 
       fill= "Partidos políticos", x=NULL, y="Total de votos por partido") +
  facet_wrap(~comuna, scales = "free_y")+
  theme_bw(base_size = 8)  +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        legend.title = element_text(face = "bold"),
        legend.text = element_text(face = "italic"),
        legend.position = "bottom",
        legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
        axis.title.x = element_text(face = "bold"),
        axis.title.y = element_text(face = "bold"))

A continuación una gráfica similar que muestre la diferencia en el número de votos:

ggplot(Can_localidad_JAL, aes(x=candidato_o_partido, y=total_votos, fill=candidato_o_partido)) +
  geom_bar(stat = "identity") +
  scale_x_discrete(NULL, labels = NULL) +
  labs(title = "Votación por partidos en las elecciones al Concejo 2019 por localidad", 
       fill= "Partidos políticos", x=NULL, y="Total de votos por partido") +
  facet_wrap(~comuna)+
  theme_bw(base_size = 8)  +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        legend.title = element_text(face = "bold"),
        legend.text = element_text(face = "italic"),
        legend.position = "bottom",
        legend.margin = margin(t = 0, r = 0, b = 0, l = 0),
        axis.title.x = element_text(face = "bold"),
        axis.title.y = element_text(face = "bold"))

Luego de tener la gráfica, grabamos el partido más votado en cada localidad en una base compatible con el shape de localidades en ArcGIS para cartografiarlo.

Partidos_JAL <- Can_localidad_JAL %>% arrange(desc(total_votos)) %>% group_by(comuna) %>% slice(1)

Partidos_JAL <- separate(Partidos_JAL, comuna, into = c("CodLoca", "Loca"), sep = " ", remove = FALSE, extra = "merge")

Partidos_JAL$Loca <- sub("USAQUÉN", "USAQUEN", Partidos_JAL$Loca)

Partidos_JAL$Loca <- sub("URIBE", "URIBE URIBE", Partidos_JAL$Loca)

Partidos_JAL$Loca <- sub("MÁRTIRES", "LOS MARTIRES", Partidos_JAL$Loca)

write.csv2(Partidos_JAL, 
           file = "C:\\Users\\tomas\\OneDrive\\Desktop\\ArcGIS\\UniAndes\\Partidos_JAL.csv")

view(Partidos_JAL)

Análisis de Concejales en cada localidad

Cargamos la base de datos de las elecciones del 2019 con resultados por candidato y por puesto.

Concejo <- read_csv2("C:\\Users\\tomas\\OneDrive\\Documents\\UniAndes\\Bogota_2019\\Bogota_2019_Concejo_candidatos.csv")
## ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
## Rows: 61082 Columns: 16
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (7): depto, municipio, nombrepuesto, corporacionocargo, nombrepartidogsc...
## dbl (9): cod_can_pp, codig, codcan, v_pp_can, cod, zona, puesto, codigo, votos
## 
## ℹ 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.
str(Concejo)
## spc_tbl_ [61,082 × 16] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ cod_can_pp                : num [1:61082] 1 2 3 4 5 6 7 8 9 10 ...
##  $ codig                     : num [1:61082] 0 0 0 1 1 1 1 1 1 1 ...
##  $ codcan                    : num [1:61082] 996 997 998 0 1 2 3 4 5 6 ...
##  $ v_pp_can                  : num [1:61082] 11643 2627 3432 836 717 ...
##  $ cod                       : num [1:61082] 1 1 1 1 1 1 1 1 1 1 ...
##  $ zona                      : num [1:61082] 5 5 5 5 5 5 6 6 5 6 ...
##  $ puesto                    : num [1:61082] 1 1 1 1 1 1 1 1 1 1 ...
##  $ codigo                    : num [1:61082] 16 16 16 16 16 16 16 16 16 16 ...
##  $ depto                     : chr [1:61082] "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." ...
##  $ municipio                 : chr [1:61082] "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." ...
##  $ nombrepuesto              : chr [1:61082] "CLASS" "FONTIBON" "BOSA" "CLASS" ...
##  $ corporacionocargo         : chr [1:61082] "CONCEJO" "CONCEJO" "CONCEJO" "CONCEJO" ...
##  $ nombrepartidogscocoalicion: chr [1:61082] "CANDIDATOS TOTALES" "CANDIDATOS TOTALES" "CANDIDATOS TOTALES" "CANDIDATOS TOTALES" ...
##  $ candidato                 : chr [1:61082] "VOTOS EN BLANCO" "VOTOS EN BLANCO" "VOTOS EN BLANCO" "VOTOS EN BLANCO" ...
##  $ votos                     : num [1:61082] 2 10 32 22 7 27 34 43 36 12 ...
##  $ _merge                    : chr [1:61082] "Matched (3)" "Matched (3)" "Matched (3)" "Matched (3)" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   cod_can_pp = col_double(),
##   ..   codig = col_double(),
##   ..   codcan = col_double(),
##   ..   v_pp_can = col_double(),
##   ..   cod = col_double(),
##   ..   zona = col_double(),
##   ..   puesto = col_double(),
##   ..   codigo = col_double(),
##   ..   depto = col_character(),
##   ..   municipio = col_character(),
##   ..   nombrepuesto = col_character(),
##   ..   corporacionocargo = col_character(),
##   ..   nombrepartidogscocoalicion = col_character(),
##   ..   candidato = col_character(),
##   ..   votos = col_double(),
##   ..   `_merge` = col_character()
##   .. )
##  - attr(*, "problems")=<externalptr>

Las localidades tienen el código zona pero no tienen el nombre, por lo que debemos asignarlo manualmente. Los nombres deben ser compatibles con el shape de Localidades en ArcGIS para hacer la unión espacial más adelante.

cod_localidades <- tibble(CodLoca = c(1:20, 90, 98), Loca = c("USAQUEN", "CHAPINERO", "SANTA FE", "SAN CRISTOBAL", "USME", "TUNJUELITO", "BOSA", "KENNEDY", "FONTIBON", "ENGATIVA", "SUBA", "BARRIOS UNIDOS", "TEUSAQUILLO", "LOS MARTIRES", "ANTONIO NARIÑO", "PUENTE ARANDA", "CANDELARIA", "RAFAEL URIBE URIBE", "CIUDAD BOLIVAR", "SUMAPAZ", "PUESTO CENSO", "CARCELES"))

cod_localidades
## # A tibble: 22 × 2
##    CodLoca Loca         
##      <dbl> <chr>        
##  1       1 USAQUEN      
##  2       2 CHAPINERO    
##  3       3 SANTA FE     
##  4       4 SAN CRISTOBAL
##  5       5 USME         
##  6       6 TUNJUELITO   
##  7       7 BOSA         
##  8       8 KENNEDY      
##  9       9 FONTIBON     
## 10      10 ENGATIVA     
## # … with 12 more rows

Con los códigos, podemos unir las dos bases de datos para poner una nueva variable con los nombres de las localidades. La variable zona en el Concejo se une con la variable CodLoca en la base de datos que acabamos de crear.

Concejo <- left_join(Concejo, cod_localidades, by = join_by("zona"=="CodLoca"))

str(Concejo)
## spc_tbl_ [61,082 × 17] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ cod_can_pp                : num [1:61082] 1 2 3 4 5 6 7 8 9 10 ...
##  $ codig                     : num [1:61082] 0 0 0 1 1 1 1 1 1 1 ...
##  $ codcan                    : num [1:61082] 996 997 998 0 1 2 3 4 5 6 ...
##  $ v_pp_can                  : num [1:61082] 11643 2627 3432 836 717 ...
##  $ cod                       : num [1:61082] 1 1 1 1 1 1 1 1 1 1 ...
##  $ zona                      : num [1:61082] 5 5 5 5 5 5 6 6 5 6 ...
##  $ puesto                    : num [1:61082] 1 1 1 1 1 1 1 1 1 1 ...
##  $ codigo                    : num [1:61082] 16 16 16 16 16 16 16 16 16 16 ...
##  $ depto                     : chr [1:61082] "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." ...
##  $ municipio                 : chr [1:61082] "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." ...
##  $ nombrepuesto              : chr [1:61082] "CLASS" "FONTIBON" "BOSA" "CLASS" ...
##  $ corporacionocargo         : chr [1:61082] "CONCEJO" "CONCEJO" "CONCEJO" "CONCEJO" ...
##  $ nombrepartidogscocoalicion: chr [1:61082] "CANDIDATOS TOTALES" "CANDIDATOS TOTALES" "CANDIDATOS TOTALES" "CANDIDATOS TOTALES" ...
##  $ candidato                 : chr [1:61082] "VOTOS EN BLANCO" "VOTOS EN BLANCO" "VOTOS EN BLANCO" "VOTOS EN BLANCO" ...
##  $ votos                     : num [1:61082] 2 10 32 22 7 27 34 43 36 12 ...
##  $ _merge                    : chr [1:61082] "Matched (3)" "Matched (3)" "Matched (3)" "Matched (3)" ...
##  $ Loca                      : chr [1:61082] "USME" "USME" "USME" "USME" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   cod_can_pp = col_double(),
##   ..   codig = col_double(),
##   ..   codcan = col_double(),
##   ..   v_pp_can = col_double(),
##   ..   cod = col_double(),
##   ..   zona = col_double(),
##   ..   puesto = col_double(),
##   ..   codigo = col_double(),
##   ..   depto = col_character(),
##   ..   municipio = col_character(),
##   ..   nombrepuesto = col_character(),
##   ..   corporacionocargo = col_character(),
##   ..   nombrepartidogscocoalicion = col_character(),
##   ..   candidato = col_character(),
##   ..   votos = col_double(),
##   ..   `_merge` = col_character()
##   .. )
##  - attr(*, "problems")=<externalptr>

Ahora creamos una base para agrupar los votos de cada candidato por localidad. En el proceso podemos limpiar la base de datos al eliminar “CANDIDATOS TOTALES” que es la suma de todos los candidatos en la localidad y “. . .” que son observaciones vacías. Luego cambiamos los caracteres especiales de “Ñ” que no se leyeron correctamente al importar el archivo .csv:

Concejo_localidad_candidato <- Concejo %>%
  subset(candidato != "CANDIDATOS TOTALES" | candidato != ". . .") %>%
  group_by(Loca, candidato, nombrepartidogscocoalicion) %>%
  reframe(votos = sum(v_pp_can)) %>%
  view()

Concejo_localidad_candidato$candidato <- str_replace_all(Concejo_localidad_candidato$candidato, "�", "Ñ")

Con la base de datos limpia solo contiene la localidad, el candidato, el nombre de la coalición o partido y los votos del candidato en esa localidad, podemos extraer los candidatos más votados de cada localidad. Para esto primero organizamos los datos de los votos de manera descendente y luego agrupamos por localidad para extraer la observación con más votos de cada localidad. Esta nueva base la exportamos para unirla con el shape de localidades en ArcGIS.

Candidatos_Concejo <- Concejo_localidad_candidato %>% arrange(desc(votos)) %>% group_by(Loca) %>% slice(1)

Candidatos_Concejo
## # A tibble: 23 × 4
## # Groups:   Loca [23]
##    Loca           candidato                                  nombreparti…¹ votos
##    <chr>          <chr>                                      <chr>         <dbl>
##  1 ANTONIO NARIÑO FLOR ELVA CARDENAS VELANDIA                G.S.C. BOGOT… 10374
##  2 BARRIOS UNIDOS MARIA FERNANDA ROJAS MANTILLA              PARTIDO ALIA…  4433
##  3 BOSA           JUAN CARLOS TRIANA RUBIANO                 PARTIDO ALIA…  9310
##  4 CANDELARIA     JOSIAS FIESCO AGUDELO                      PARTIDO CENT…   681
##  5 CARCELES       GERMAN AUGUSTO GARCIA MAYA                 PARTIDO LIBE…     1
##  6 CHAPINERO      JORGE DURAN SILVA                          PARTIDO LIBE…   946
##  7 CIUDAD BOLIVAR ARMANDO DE LOS MILAGROS GUTIERREZ GONZALEZ PARTIDO LIBE…   120
##  8 ENGATIVA       DIEGO ANDRES CANCINO MARTINEZ              PARTIDO ALIA…   481
##  9 FONTIBON       CLAUDIA XIMENA MARIA CARRILLO SANTOS       PARTIDO ALIA…    54
## 10 KENNEDY        MANUEL JOSE SARMIENTO ARGUELLO             PARTIDO POLO…  6075
## # … with 13 more rows, and abbreviated variable name
## #   ¹​nombrepartidogscocoalicion
write.csv2(Candidatos_Concejo, 
           file = "C:\\Users\\tomas\\OneDrive\\Desktop\\ArcGIS\\UniAndes\\Candidatos_Concejo.csv")

Análisis por candidatos a la JAL en 2019

Para importar la base de datos a R, primero debemos limpiarla en Stata. La base de datos original tiene las observaciones por mesa electoral en cada puesto, por lo que primero hay que colapsarla creando un código para cada candidato en su puesto. egen crea una nueva variable y =group hace que la variable sea única para cada puesto, localidad y candidato.

Stata JAL 2019

El código es:

Luego calculamos los votos de cada candidato por el puesto:

Ahora podemos colapsar la base de datos para que cada observación sea un candidato por puesto y no por mesa, al colapsar podemos introducir todas las variables numéricas con su promedio, y colapsamos por la nueva variable del código del candidato por puesto. Finalmente, guardamos provisionalmente la información en formato .dta:

Para recuperar las variables no numéricas, como el nombre del candidato, del puesto y del partido. Hacemos un merge con otra base de datos que incluya la variable cod_can_pp. Para esto repetimos los primeros dos pasos y guardamos la base como to_merge.dta:

Ahora traemos la primera base para hacer el merge uno a uno por observaciones.

Result                      Number of obs
-----------------------------------------
Not matched                       772,765
    from master                         0  (_merge==1)
    from using                    772,765  (_merge==2)

Matched                            76,103  (_merge==3)
-----------------------------------------

En el resultado vemos que hay unas observaciones que no tienen un match, por lo que las podemos eliminar.

Finalmente guardamos y exportamos a excel con las primeras filas como variables.

Desde excel podemos guardar el archivo como .csv y traerlo a R.

R Jal 2019

Ahora importamos el archivo R con las elecciones a la JAL 2019 por candidato y por puesto electoral. Para agregar la columna con el nombre de las localidades, repetimos el proceso de la base de Concejo con el código de cada localidad.

JAL <- read_csv2("C:\\Users\\tomas\\OneDrive\\Documents\\UniAndes\\Bogota_2019\\Bogota_2019_JAL_candidatos.csv")
## ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
## Rows: 76103 Columns: 16
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (7): depto, municipio, nombrepuesto, corporacionocargo, nombrepartidogsc...
## dbl (9): cod_can_pp, zona, puesto, codig, codcan, v_can_pp, codigo, cod, votos
## 
## ℹ 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.
str(JAL)
## spc_tbl_ [76,103 × 16] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ cod_can_pp                : num [1:76103] 1 2 3 4 5 6 7 8 9 10 ...
##  $ zona                      : num [1:76103] 1 1 1 1 1 1 1 1 1 1 ...
##  $ puesto                    : num [1:76103] 1 1 1 1 1 1 1 1 1 1 ...
##  $ codig                     : num [1:76103] 1 1 1 1 1 1 1 1 1 1 ...
##  $ codcan                    : num [1:76103] 0 81 82 83 84 85 86 87 88 89 ...
##  $ v_can_pp                  : num [1:76103] 135764 135764 135764 135764 135764 ...
##  $ codigo                    : num [1:76103] 16 16 16 16 16 16 16 16 16 16 ...
##  $ depto                     : chr [1:76103] "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." ...
##  $ cod                       : num [1:76103] 1 1 1 1 1 1 1 1 1 1 ...
##  $ municipio                 : chr [1:76103] "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." ...
##  $ nombrepuesto              : chr [1:76103] "USAQUEN" "USAQUEN" "USAQUEN" "USAQUEN" ...
##  $ corporacionocargo         : chr [1:76103] "JAL" "JAL" "JAL" "JAL" ...
##  $ nombrepartidogscocoalicion: chr [1:76103] "PARTIDO LIBERAL COLOMBIANO" "PARTIDO LIBERAL COLOMBIANO" "PARTIDO LIBERAL COLOMBIANO" "PARTIDO LIBERAL COLOMBIANO" ...
##  $ candidato                 : chr [1:76103] "PARTIDO LIBERAL COLOMBIANO" "NICOLAS GUTIERREZ BERMUDEZ" "GERARDO SARMIENTO CHACON" "CARLOS ALBERTO CRESPO CARRILLO" ...
##  $ votos                     : num [1:76103] 2 3 1 3 3 1 1 1 1 2 ...
##  $ _merge                    : chr [1:76103] "Matched (3)" "Matched (3)" "Matched (3)" "Matched (3)" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   cod_can_pp = col_double(),
##   ..   zona = col_double(),
##   ..   puesto = col_double(),
##   ..   codig = col_double(),
##   ..   codcan = col_double(),
##   ..   v_can_pp = col_double(),
##   ..   codigo = col_double(),
##   ..   depto = col_character(),
##   ..   cod = col_double(),
##   ..   municipio = col_character(),
##   ..   nombrepuesto = col_character(),
##   ..   corporacionocargo = col_character(),
##   ..   nombrepartidogscocoalicion = col_character(),
##   ..   candidato = col_character(),
##   ..   votos = col_double(),
##   ..   `_merge` = col_character()
##   .. )
##  - attr(*, "problems")=<externalptr>
JAL <- left_join(JAL, cod_localidades, by = join_by("zona"=="CodLoca"))

Limpiamos la base de datos para obtener los votos por localidad, arreglamos caracteres especiales y extraemos candidatos más votados para exportar.

JAL_localidad_candidato <- JAL %>%
  subset(candidato != "CANDIDATOS TOTALES" &  candidato != "VOTOS EN BLANCO ." & candidato != "PARTIDO ALIANZA VERDE" & candidato != "PARTIDO CENTRO DEMOCRATICO" & candidato != "PARTIDO COLOMBIA JUSTA LIBRES" & candidato != "VOTOS NULOS ." & candidato != "VOTOS NO MARCADOS ." & candidato != "PARTIDO LIBERAL COLOMBIANO" & candidato != "PARTIDO CAMBIO RADICAL" & candidato != "COALICION COLOMBIA HUMANA USAQUEN" & candidato != "G.S.C. BOGOTA PARA LA GENTE") %>%
  group_by(Loca, candidato, nombrepartidogscocoalicion) %>%
  reframe(votos = sum(v_can_pp)) %>%
  view() 

JAL_localidad_candidato$candidato <- str_replace_all(JAL_localidad_candidato$candidato, "�", "Ñ")

Candidatos_JAL <- JAL_localidad_candidato %>% arrange(desc(votos)) %>% group_by(Loca) %>% slice(1)

Candidatos_JAL
## # A tibble: 20 × 4
## # Groups:   Loca [20]
##    Loca               candidato                    nombrepartidogscocoa…¹  votos
##    <chr>              <chr>                        <chr>                   <dbl>
##  1 ANTONIO NARIÑO     JOSE FRANCISCO TENJO TENJO   PARTIDO ALIANZA VERDE  1.67e6
##  2 BARRIOS UNIDOS     JOSE NORBERTO BELTRAN URREGO PARTIDO ALIANZA VERDE  2.63e6
##  3 BOSA               JULIAN USCATEGUI PASTRANA    PARTIDO CENTRO DEMOCR… 5.10e6
##  4 CANDELARIA         JESUS MARIA VIVAS MOSQUERA   PARTIDO CENTRO DEMOCR… 1.47e6
##  5 CHAPINERO          JOSE NORBERTO BELTRAN URREGO PARTIDO ALIANZA VERDE  2.23e6
##  6 CIUDAD BOLIVAR     NICOLAS GUTIERREZ BERMUDEZ   PARTIDO LIBERAL COLOM… 4.82e6
##  7 ENGATIVA           JOSE NORBERTO BELTRAN URREGO PARTIDO ALIANZA VERDE  5.69e6
##  8 FONTIBON           NICOLAS GUTIERREZ BERMUDEZ   PARTIDO LIBERAL COLOM… 3.72e6
##  9 KENNEDY            JOSE NORBERTO BELTRAN URREGO PARTIDO ALIANZA VERDE  6.31e6
## 10 LOS MARTIRES       JESUS DAVID ARAQUE MEJIA     G.S.C. BOGOTA PARA LA… 2.81e6
## 11 PUENTE ARANDA      EDUARDO TORRES NARANJO       PARTIDO LIBERAL COLOM… 4.81e6
## 12 RAFAEL URIBE URIBE JOSE NORBERTO BELTRAN URREGO PARTIDO ALIANZA VERDE  4.93e6
## 13 SAN CRISTOBAL      JESUS MARIA VIVAS MOSQUERA   PARTIDO CENTRO DEMOCR… 5.76e6
## 14 SANTA FE           JESUS DAVID ARAQUE MEJIA     G.S.C. BOGOTA PARA LA… 2.07e6
## 15 SUBA               JOSE NORBERTO BELTRAN URREGO PARTIDO ALIANZA VERDE  5.37e6
## 16 SUMAPAZ            SANDRA MONICA BARRERA BERNAL PARTIDO CONSERVADOR C… 5.93e5
## 17 TEUSAQUILLO        JESUS MARIA VIVAS MOSQUERA   PARTIDO CENTRO DEMOCR… 3.77e6
## 18 TUNJUELITO         JOSE NORBERTO BELTRAN URREGO PARTIDO ALIANZA VERDE  2.98e6
## 19 USAQUEN            JESUS MARIA VIVAS MOSQUERA   PARTIDO CENTRO DEMOCR… 5.30e6
## 20 USME               JOSE NORBERTO BELTRAN URREGO PARTIDO ALIANZA VERDE  4.14e6
## # … with abbreviated variable name ¹​nombrepartidogscocoalicion
write.csv2(Candidatos_JAL, 
           file = "C:\\Users\\tomas\\OneDrive\\Desktop\\ArcGIS\\UniAndes\\Candidatos_JAL.csv")

Análisis electoral a nivel UPZ.

Importamos una base de datos resultado de la unión espacial de la base de datos original con el shape de Unidades de Planeamiento Zonal de Bogotá.

Elecciones_upz <- read_csv2("C:\\Users\\tomas\\OneDrive\\Documents\\UniAndes\\Puestos por UPZ.csv")
## ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
## Rows: 962 Columns: 26
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (11): pp, departamen, municipio, puesto, comuna, direccion, NOMBRE_UPZ, ...
## dbl (15): TARGET_FID, zz, mujeres, hombres, total, mesas, POINT_X, POINT_Y, ...
## 
## ℹ 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.
str(Elecciones_upz)
## spc_tbl_ [962 × 26] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ TARGET_FID: num [1:962] 0 1 2 3 4 5 6 7 8 9 ...
##  $ zz        : num [1:962] 1 1 1 1 1 1 1 1 1 1 ...
##  $ pp        : chr [1:962] "1" "2" "3" "4" ...
##  $ departamen: chr [1:962] "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." ...
##  $ municipio : chr [1:962] "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." "BOGOTA. D.C." ...
##  $ puesto    : chr [1:962] "USAQU\xc9N" "SERVITA" "CALAZANS" "COLEGIO AQUILEO PARRA SEDE BACHILLERATO" ...
##  $ mujeres   : num [1:962] 13950 13625 5437 8200 6244 ...
##  $ hombres   : num [1:962] 16060 11010 4653 6855 5472 ...
##  $ total     : num [1:962] 30010 24635 10090 15055 11716 ...
##  $ mesas     : num [1:962] 88 72 30 44 35 35 37 62 48 47 ...
##  $ comuna    : chr [1:962] "01LOCALIDAD 1 USAQUEN" "01LOCALIDAD 1 USAQUEN" "01LOCALIDAD 1 USAQUEN" "01LOCALIDAD 1 USAQUEN" ...
##  $ direccion : chr [1:962] "CARRERA 6A ENTRE CALLE 119 Y 120A VIA PUBLICA" "CALLE 165 # 7-38/52" "CARRERA 20A #173A-10 ENTRADA AL PARQUEADERO" "CARRERA 18A #187-75 Y CARRERA 18A # 187-97" ...
##  $ POINT_X   : num [1:962] -74 -74 -74 -74 -74 ...
##  $ POINT_Y   : num [1:962] 4.7 4.74 4.75 4.77 4.77 ...
##  $ NUMERO    : num [1:962] 14 10 10 9 9 9 13 13 14 15 ...
##  $ NOMBRE_UPZ: chr [1:962] "USAQUEN" "LA URIBE" "LA URIBE" "VERBENAL" ...
##  $ CLASIFICAC: chr [1:962] "e" "h" "h" "a" ...
##  $ TIPO_UPZ  : num [1:962] 5 8 8 1 1 1 3 3 5 8 ...
##  $ DESC_TIPO : chr [1:962] "CON CENTRALIDAD URBANA" "PREDOMINANTEMENTE DOTACIONAL" "PREDOMINANTEMENTE DOTACIONAL" "RESIDENCIAL DE URBANIZACION INCOMPLETA" ...
##  $ NLOCALIDAD: num [1:962] 1 1 1 1 1 1 1 1 1 1 ...
##  $ LOCALIDAD : chr [1:962] "USAQUEN" "USAQUEN" "USAQUEN" "USAQUEN" ...
##  $ ESTRATOS  : chr [1:962] "ESTRATOS VARIOS" "ESTRATOS VARIOS" "ESTRATOS VARIOS" "ESTRATOS VARIOS" ...
##  $ COD_ESTRAT: num [1:962] 123456 1234 1234 12345 12345 ...
##  $ AREA      : num [1:962] 4942586 3518400 3518400 3485822 3485822 ...
##  $ PERIMETER : num [1:962] 14761 10714 10714 8745 8745 ...
##  $ HECTARES  : num [1:962] 494 352 352 349 349 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   TARGET_FID = col_double(),
##   ..   zz = col_double(),
##   ..   pp = col_character(),
##   ..   departamen = col_character(),
##   ..   municipio = col_character(),
##   ..   puesto = col_character(),
##   ..   mujeres = col_double(),
##   ..   hombres = col_double(),
##   ..   total = col_double(),
##   ..   mesas = col_double(),
##   ..   comuna = col_character(),
##   ..   direccion = col_character(),
##   ..   POINT_X = col_double(),
##   ..   POINT_Y = col_double(),
##   ..   NUMERO = col_double(),
##   ..   NOMBRE_UPZ = col_character(),
##   ..   CLASIFICAC = col_character(),
##   ..   TIPO_UPZ = col_double(),
##   ..   DESC_TIPO = col_character(),
##   ..   NLOCALIDAD = col_double(),
##   ..   LOCALIDAD = col_character(),
##   ..   ESTRATOS = col_character(),
##   ..   COD_ESTRAT = col_double(),
##   ..   AREA = col_double(),
##   ..   PERIMETER = col_double(),
##   ..   HECTARES = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>

Ahora procedemos a unirla con la base de elecciones según el puesto electoral y la UPZ en la que se ubica el puesto. La información se consiguió al importar la base de elecciones a ArcGIS y hacer una unión espacial con el shape de UPZs.

Elecciones_upz <- left_join(Elecciones, Elecciones_upz, by = join_by("puesto" == "puesto"))
## Warning in left_join(Elecciones, Elecciones_upz, by = join_by("puesto" == : Each row in `x` is expected to match at most 1 row in `y`.
## ℹ Row 19416 of `x` matches multiple rows.
## ℹ If multiple matches are expected, set `multiple = "all"` to silence this
##   warning.
summary(Elecciones_upz)
##      depto    depto_municipio      comuna.x              zona      
##  Min.   :16   Length:105299      Length:105299      Min.   : 1.00  
##  1st Qu.:16   Class :character   Class :character   1st Qu.: 7.00  
##  Median :16   Mode  :character   Mode  :character   Median :10.00  
##  Mean   :16                                         Mean   :10.22  
##  3rd Qu.:16                                         3rd Qu.:13.00  
##  Max.   :16                                         Max.   :98.00  
##                                                                    
##            eleccion      cod_eleccion    codpuesto           grupuesto    
##  Camara 2022   :31872   Min.   :1.000   Length:105299      Min.   :  1.0  
##  Senado 2022   :19809   1st Qu.:4.000   Class :character   1st Qu.:231.0  
##  Concejo 2019  :13607   Median :6.000   Mode  :character   Median :443.0  
##  JAL 2019      :11585   Mean   :5.622                      Mean   :444.6  
##  Presi 1 v 2022: 8864   3rd Qu.:7.000                      3rd Qu.:667.0  
##  Presi 1 v 2018: 6753   Max.   :9.000                      Max.   :898.0  
##  (Other)       :12809                                      NA's   :1709   
##     puesto            posicion            codpetro       candidato_o_partido
##  Length:105299      Length:105299      Min.   :0.00000   Length:105299      
##  Class :character   Class :character   1st Qu.:0.00000   Class :character   
##  Mode  :character   Mode  :character   Median :0.00000   Mode  :character   
##                                        Mean   :0.02937                      
##                                        3rd Qu.:0.00000                      
##                                        Max.   :1.00000                      
##                                                                             
##   v_can_pp_ele   porc_v_can_pp_ele  tot_v_pp_ele      v_can_pp       
##  Min.   :    1   Min.   : 0.0030   Min.   :   13   Min.   :     1.0  
##  1st Qu.:    4   1st Qu.: 0.1812   1st Qu.: 1401   1st Qu.:     6.0  
##  Median :   31   Median : 1.9694   Median : 3473   Median :    78.0  
##  Mean   :  290   Mean   : 6.9864   Mean   : 4152   Mean   :   767.8  
##  3rd Qu.:  216   3rd Qu.: 6.9336   3rd Qu.: 5952   3rd Qu.:   573.0  
##  Max.   :47119   Max.   :98.8971   Max.   :95018   Max.   :138420.0  
##                                                                      
##  porc_v_can_pp         tot_v_pp      v_can_zona_ele   porc_v_can_zona_ele
##  Min.   : 0.00022   Min.   :    25   Min.   :     1   Min.   : 0.00042   
##  1st Qu.: 0.03080   1st Qu.: 11987   1st Qu.:   277   1st Qu.: 0.17490   
##  Median : 0.53040   Median : 33083   Median :  3434   Median : 2.17528   
##  Mean   : 2.22352   Mean   : 38915   Mean   : 16588   Mean   : 6.96131   
##  3rd Qu.: 2.37858   3rd Qu.: 56832   3rd Qu.: 15132   3rd Qu.: 6.97578   
##  Max.   :70.99768   Max.   :458474   Max.   :299349   Max.   :82.60870   
##                                                                          
##  tot_v_zona_ele     v_can_zona     porc_v_can_zona      tot_v_zona     
##  Min.   :   366   Min.   :     1   Min.   : 0.00004   Min.   :   5327  
##  1st Qu.:114412   1st Qu.:   496   1st Qu.: 0.02614   1st Qu.:1196281  
##  Median :198233   Median :  8918   Median : 0.57989   Median :2054084  
##  Mean   :228139   Mean   : 44431   Mean   : 2.07798   Mean   :2187055  
##  3rd Qu.:355499   3rd Qu.: 39766   3rd Qu.: 2.43619   3rd Qu.:3377184  
##  Max.   :562680   Max.   :930456   Max.   :36.54965   Max.   :4317729  
##                                                                        
##  direccion.x          POINT_X.x        POINT_Y.x       TARGET_FID   
##  Length:105299      Min.   :-74.36   Min.   :3.986   Min.   :  1.0  
##  Class :character   1st Qu.:-74.14   1st Qu.:4.584   1st Qu.:255.0  
##  Mode  :character   Median :-74.11   Median :4.622   Median :476.0  
##                     Mean   :-74.11   Mean   :4.631   Mean   :488.1  
##                     3rd Qu.:-74.08   3rd Qu.:4.683   3rd Qu.:739.0  
##                     Max.   :-74.02   Max.   :4.819   Max.   :961.0  
##                     NA's   :1967     NA's   :1967    NA's   :17934  
##        zz             pp             departamen         municipio        
##  Min.   : 1.00   Length:105299      Length:105299      Length:105299     
##  1st Qu.: 7.00   Class :character   Class :character   Class :character  
##  Median :10.00   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :10.64                                                           
##  3rd Qu.:14.00                                                           
##  Max.   :98.00                                                           
##  NA's   :17934                                                           
##     mujeres          hombres           total            mesas       
##  Min.   :     0   Min.   :     0   Min.   :     0   Min.   :  0.00  
##  1st Qu.:  1478   1st Qu.:  1310   1st Qu.:  2813   1st Qu.:  9.00  
##  Median :  3346   Median :  2975   Median :  6414   Median : 19.00  
##  Mean   :  3988   Mean   :  3574   Mean   :  7562   Mean   : 21.32  
##  3rd Qu.:  5317   3rd Qu.:  4695   3rd Qu.: 10006   3rd Qu.: 30.00  
##  Max.   :159623   Max.   :175834   Max.   :335457   Max.   :281.00  
##  NA's   :17934    NA's   :17934    NA's   :17934    NA's   :17934   
##    comuna.y         direccion.y          POINT_X.y        POINT_Y.y    
##  Length:105299      Length:105299      Min.   :-74.36   Min.   :0.000  
##  Class :character   Class :character   1st Qu.:-74.15   1st Qu.:4.578  
##  Mode  :character   Mode  :character   Median :-74.11   Median :4.617  
##                                        Mean   :-73.90   Mean   :4.608  
##                                        3rd Qu.:-74.09   3rd Qu.:4.673  
##                                        Max.   :  0.00   Max.   :4.819  
##                                        NA's   :17934    NA's   :17934  
##      NUMERO        NOMBRE_UPZ         CLASIFICAC           TIPO_UPZ    
##  Min.   :  0.00   Length:105299      Length:105299      Min.   :0.000  
##  1st Qu.: 38.00   Class :character   Class :character   1st Qu.:1.000  
##  Median : 57.00   Mode  :character   Mode  :character   Median :2.000  
##  Mean   : 59.64                                         Mean   :2.483  
##  3rd Qu.: 84.00                                         3rd Qu.:3.000  
##  Max.   :115.00                                         Max.   :8.000  
##  NA's   :17934                                          NA's   :17934  
##   DESC_TIPO           NLOCALIDAD      LOCALIDAD           ESTRATOS        
##  Length:105299      Min.   : 0.000   Length:105299      Length:105299     
##  Class :character   1st Qu.: 7.000   Class :character   Class :character  
##  Mode  :character   Median :10.000   Mode  :character   Mode  :character  
##                     Mean   : 9.975                                        
##                     3rd Qu.:14.000                                        
##                     Max.   :19.000                                        
##                     NA's   :17934                                         
##    COD_ESTRAT            AREA           PERIMETER        HECTARES    
##  Min.   :     0.0   Min.   :      0   Min.   :    0   Min.   :  0.0  
##  1st Qu.:     3.0   1st Qu.:2665529   1st Qu.: 7767   1st Qu.:266.6  
##  Median :    23.0   Median :3851606   Median : 9477   Median :385.2  
##  Mean   :   728.8   Mean   :3913097   Mean   :10215   Mean   :391.3  
##  3rd Qu.:    34.0   3rd Qu.:4832222   3rd Qu.:13180   3rd Qu.:483.2  
##  Max.   :123456.0   Max.   :9923308   Max.   :22563   Max.   :992.3  
##  NA's   :17934      NA's   :17934     NA's   :17934   NA's   :17934

Con lal informaición de la UPZ de cada puesto, los votos por puesto y sus partidos, podemos hacer el mismo proceso de antes:

# Creamos una base que elimine los datos vacíos, agrupe las observaciones según la upz, y calcule el número de votos y el promedio de cada candidato en sus UPZ. 

eleccion_upz_partido <- Elecciones_upz %>%
  drop_na() %>%
  group_by(eleccion, NOMBRE_UPZ, candidato_o_partido) %>%
  reframe(total_votos = sum(v_can_zona_ele), 
          porc_votos = sum(v_can_zona_ele)/sum(tot_v_zona_ele)*100) %>%
  distinct() %>%
  view()

# Esta nueva base la filtramos para solo obtener datos de la elección a las JAL y limpiamos para que solo aparezcan partidos y con el mismo nombre en todas las localidades. 

Can_upz_JAL <- eleccion_upz_partido %>%
  subset(eleccion == "JAL 2019" & candidato_o_partido != "CANDIDATOS TOTALES")

Can_upz_JAL$candidato_o_partido = sub(".*HUMANA.*", "COALICIÓN COLOMBIA HUMANA", Can_upz_JAL$candidato_o_partido)

# La base limpia ahora se puede ordenar en función de los votos para sacar el partido más votado de cada UPZ. 

Partidos_JAL_upz <- Can_upz_JAL  %>% 
  subset(candidato_o_partido!= "VOTOS EN BLANCO") %>% 
  arrange(desc(total_votos)) %>% 
  group_by(NOMBRE_UPZ) %>% 
  slice(1)

# Se exporta para hacer la unión con el shape de UPZ en ArcGIS

write.csv2(Partidos_JAL_upz, 
           file = "C:\\Users\\tomas\\OneDrive\\Desktop\\ArcGIS\\UniAndes\\Partidos_JAL_upz.csv")

view(Partidos_JAL_upz)

Análisis por UPZ de elecciones al Concejo 2019

El proceso es igual desde la creación de una base que solo incluya votos al Concejo de Bogotá.

Can_upz_concejo <- eleccion_upz_partido %>%
  subset(eleccion == "Concejo 2019" & candidato_o_partido != "CANDIDATOS TOTALES")

Can_upz_concejo$candidato_o_partido = sub(".*HUMANA.*", "COALICIÓN COLOMBIA HUMANA", Can_upz_concejo$candidato_o_partido)

Partidos_concejo_upz <- Can_upz_concejo  %>% 
  arrange(desc(total_votos)) %>% 
  group_by(NOMBRE_UPZ) %>% 
  slice(1)

write.csv2(Partidos_concejo_upz, 
           file = "C:\\Users\\tomas\\OneDrive\\Desktop\\ArcGIS\\UniAndes\\Partidos_concejo_upz.csv")

view(Partidos_concejo_upz)

Análisis por barrio

Con el shape de barrios en ArcGIS, podemos hacer una unión espacial con los puntos de los puestos de votación en Bogotá para obtener el barrio de cada puesto. Como son muchas observaciones por la cantidad de barrios, recortamos todas las columnas que no sean escenciales para poder usarlo en R.

Como ArcGIS tiene problemas para exportar la tabla de la unión al excel, exportamos la tabla a .txt y la abrimos manualmente con excel usando la coma como el delimitador. Limpiamos la base en excel, eliminamos columnas no escenciales y la traemos a R.

El resultado es el mismo que anteriormente, con la única diferencia de que por el tamaño de la base, el join divide algunas variables en variable.x y variable.y. Por esto en elección utilizamos eleccion.x que contiene la información sobre las elecciones.

Comenzamos con las elecciones a la JAL.

Elecciones_barr <- read_csv2("C:\\Users\\tomas\\OneDrive\\Documents\\UniAndes\\Puestos por barrio.csv", locale=locale(encoding="latin1"))
## ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
## Rows: 104666 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr (5): eleccion, puesto, posicion, candidato_, NOMB_BARR
## dbl (5): zona, cod_elecci, BARRIO_, BARRIO_ID, COD_BAR
## 
## ℹ 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.
str(Elecciones_barr)
## spc_tbl_ [104,666 × 10] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ zona      : num [1:104666] 1 1 1 1 1 1 1 1 1 1 ...
##  $ eleccion  : chr [1:104666] "Alcaldia 2019" "Alcaldia 2019" "Alcaldia 2019" "Alcaldia 2019" ...
##  $ cod_elecci: num [1:104666] 3 3 3 3 3 3 3 3 3 3 ...
##  $ puesto    : chr [1:104666] "ALESSANDRO VOLTA" "ALESSANDRO VOLTA" "ALESSANDRO VOLTA" "ALESSANDRO VOLTA" ...
##  $ posicion  : chr [1:104666] "CENTRO" "CENTRO" "IZQUIERDA" "DERECHA" ...
##  $ candidato_: chr [1:104666] "CARLOS FERNANDO GALAN PACHON" "CLAUDIA NAYIBE LOPEZ HERNANDEZ" "HOLLMAN MORRIS" "MIGUEL URIBE TURBAY" ...
##  $ BARRIO_   : num [1:104666] 181 181 181 181 181 181 181 84 84 84 ...
##  $ BARRIO_ID : num [1:104666] 189 189 189 189 189 189 189 85 85 85 ...
##  $ NOMB_BARR : chr [1:104666] "USAQUEN" "USAQUEN" "USAQUEN" "USAQUEN" ...
##  $ COD_BAR   : num [1:104666] 8407 8407 8407 8407 8407 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   zona = col_double(),
##   ..   eleccion = col_character(),
##   ..   cod_elecci = col_double(),
##   ..   puesto = col_character(),
##   ..   posicion = col_character(),
##   ..   candidato_ = col_character(),
##   ..   BARRIO_ = col_double(),
##   ..   BARRIO_ID = col_double(),
##   ..   NOMB_BARR = col_character(),
##   ..   COD_BAR = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>
Elecciones_barr <- left_join(Elecciones, Elecciones_barr, by = join_by("puesto" == "puesto"))
## Warning in left_join(Elecciones, Elecciones_barr, by = join_by("puesto" == : Each row in `x` is expected to match at most 1 row in `y`.
## ℹ Row 1 of `x` matches multiple rows.
## ℹ If multiple matches are expected, set `multiple = "all"` to silence this
##   warning.
summary(Elecciones_barr)
##      depto    depto_municipio       comuna              zona.x     
##  Min.   :16   Length:12821588    Length:12821588    Min.   : 1.00  
##  1st Qu.:16   Class :character   Class :character   1st Qu.: 7.00  
##  Median :16   Mode  :character   Mode  :character   Median :10.00  
##  Mean   :16                                         Mean   :10.13  
##  3rd Qu.:16                                         3rd Qu.:13.00  
##  Max.   :16                                         Max.   :98.00  
##                                                                    
##           eleccion.x       cod_eleccion    codpuesto           grupuesto     
##  Camara 2022   :3954932   Min.   :1.000   Length:12821588    Min.   :  1.0   
##  Senado 2022   :2366206   1st Qu.:4.000   Class :character   1st Qu.:233.0   
##  Concejo 2019  :1641037   Median :6.000   Mode  :character   Median :437.0   
##  JAL 2019      :1417195   Mean   :5.604                      Mean   :439.8   
##  Presi 1 v 2022:1042101   3rd Qu.:7.000                      3rd Qu.:661.0   
##  Presi 1 v 2018: 850957   Max.   :9.000                      Max.   :898.0   
##  (Other)       :1549160                                      NA's   :101193  
##     puesto           posicion.x           codpetro       candidato_o_partido
##  Length:12821588    Length:12821588    Min.   :0.00000   Length:12821588    
##  Class :character   Class :character   1st Qu.:0.00000   Class :character   
##  Mode  :character   Mode  :character   Median :0.00000   Mode  :character   
##                                        Mean   :0.02866                      
##                                        3rd Qu.:0.00000                      
##                                        Max.   :1.00000                      
##                                                                             
##   v_can_pp_ele     porc_v_can_pp_ele  tot_v_pp_ele      v_can_pp       
##  Min.   :    1.0   Min.   : 0.0030   Min.   :   13   Min.   :     1.0  
##  1st Qu.:    4.0   1st Qu.: 0.1562   1st Qu.: 1953   1st Qu.:     7.0  
##  Median :   37.0   Median : 1.8126   Median : 3936   Median :    97.0  
##  Mean   :  314.6   Mean   : 6.7963   Mean   : 4554   Mean   :   842.1  
##  3rd Qu.:  245.0   3rd Qu.: 6.6838   3rd Qu.: 6269   3rd Qu.:   669.0  
##  Max.   :47119.0   Max.   :98.8971   Max.   :95018   Max.   :138420.0  
##                                                                        
##  porc_v_can_pp         tot_v_pp      v_can_zona_ele   porc_v_can_zona_ele
##  Min.   : 0.00022   Min.   :    25   Min.   :     1   Min.   : 0.00042   
##  1st Qu.: 0.02555   1st Qu.: 18510   1st Qu.:   259   1st Qu.: 0.15385   
##  Median : 0.48637   Median : 38350   Median :  3214   Median : 2.00980   
##  Mean   : 2.09423   Mean   : 43290   Mean   : 16320   Mean   : 6.77982   
##  3rd Qu.: 2.30550   3rd Qu.: 60380   3rd Qu.: 14535   3rd Qu.: 6.79282   
##  Max.   :70.99768   Max.   :458474   Max.   :299349   Max.   :82.60870   
##                                                                          
##  tot_v_zona_ele     v_can_zona     porc_v_can_zona      tot_v_zona     
##  Min.   :   366   Min.   :     1   Min.   : 0.00004   Min.   :   5327  
##  1st Qu.:119698   1st Qu.:   439   1st Qu.: 0.02286   1st Qu.:1212462  
##  Median :202156   Median :  8009   Median : 0.52582   Median :2054084  
##  Mean   :230112   Mean   : 43771   Mean   : 2.02584   Mean   :2208152  
##  3rd Qu.:355499   3rd Qu.: 39337   3rd Qu.: 2.32018   3rd Qu.:3377184  
##  Max.   :562680   Max.   :930456   Max.   :36.54965   Max.   :4317729  
##                                                                        
##   direccion            POINT_X          POINT_Y           zona.y     
##  Length:12821588    Min.   :-74.36   Min.   :3.99     Min.   : 1.00  
##  Class :character   1st Qu.:-74.15   1st Qu.:4.58     1st Qu.: 7.00  
##  Mode  :character   Median :-74.11   Median :4.62     Median :10.00  
##                     Mean   :-74.11   Mean   :4.63     Mean   :10.13  
##                     3rd Qu.:-74.09   3rd Qu.:4.68     3rd Qu.:13.00  
##                     Max.   :-74.02   Max.   :4.82     Max.   :98.00  
##                     NA's   :124323   NA's   :124323                  
##   eleccion.y          cod_elecci     posicion.y         candidato_       
##  Length:12821588    Min.   :1.000   Length:12821588    Length:12821588   
##  Class :character   1st Qu.:4.000   Class :character   Class :character  
##  Mode  :character   Median :6.000   Mode  :character   Mode  :character  
##                     Mean   :5.604                                        
##                     3rd Qu.:7.000                                        
##                     Max.   :9.000                                        
##                                                                          
##     BARRIO_        BARRIO_ID      NOMB_BARR            COD_BAR      
##  Min.   :  0.0   Min.   :  0.0   Length:12821588    Min.   :  1102  
##  1st Qu.:204.0   1st Qu.:209.0   Class :character   1st Qu.:  2552  
##  Median :437.0   Median :440.0   Mode  :character   Median :  5304  
##  Mean   :416.3   Mean   :422.5                      Mean   : 24085  
##  3rd Qu.:617.0   3rd Qu.:624.0                      3rd Qu.:  8503  
##  Max.   :844.0   Max.   :853.0                      Max.   :180403  
##                                                     NA's   :168407
eleccion_barr_partido <- Elecciones_barr %>%
  drop_na() %>%
  group_by(eleccion.x, NOMB_BARR, BARRIO_ID, candidato_o_partido) %>%
  reframe(total_votos = sum(v_can_zona_ele), 
          porc_votos = sum(v_can_zona_ele)/sum(tot_v_zona_ele)*100) %>%
  distinct() %>%
  view()

Can_barr_JAL <- eleccion_barr_partido %>%
  subset(eleccion.x == "JAL 2019" & candidato_o_partido != "CANDIDATOS TOTALES")

Can_barr_JAL$candidato_o_partido = sub(".*HUMANA.*", "COALICIÓN COLOMBIA HUMANA", Can_barr_JAL$candidato_o_partido)

Partidos_JAL_barr <- Can_barr_JAL  %>% 
  subset(candidato_o_partido!= "VOTOS EN BLANCO") %>% 
  arrange(desc(total_votos)) %>% 
  group_by(NOMB_BARR, BARRIO_ID) %>% 
  slice(1)

write.csv2(Partidos_JAL_barr, 
           file = "C:\\Users\\tomas\\OneDrive\\Desktop\\ArcGIS\\UniAndes\\Partidos_JAL_barr.csv")

view(Partidos_JAL_barr)

Y finalizamos con las elecciones al Concejo.

Can_barr_concejo <- eleccion_barr_partido %>%
  subset(eleccion.x == "Concejo 2019" & candidato_o_partido != "CANDIDATOS TOTALES")

Can_barr_concejo$candidato_o_partido = sub(".*HUMANA.*", "COALICIÓN COLOMBIA HUMANA", Can_barr_concejo$candidato_o_partido)

Partidos_concejo_barr <- Can_barr_concejo  %>% 
  subset(candidato_o_partido!= "VOTOS EN BLANCO") %>% 
  arrange(desc(total_votos)) %>% 
  group_by(NOMB_BARR, BARRIO_ID) %>% 
  slice(1)

write.csv2(Partidos_concejo_barr, 
           file = "C:\\Users\\tomas\\OneDrive\\Desktop\\ArcGIS\\UniAndes\\Partidos_concejo_barr.csv")

view(Partidos_concejo_barr)