Introducción
La corrupción se ha posicionado como el principal problema que preocupa a los colombianos de cara a la elección del próximo presidente, según la última encuesta de Invamer (10 de junio 2022), se convierte en el reflejo de la importancia y la impotencia para combatir este flagelo que le quita $50 billones de pesos colombianos anuales al país, según entes de control.
En este proyecto intenta ser una respuesta a la siguiente pregunta: Cuál es la esperanza del voto en las ciudades con más casos de corrupción detectados en Colombia?

En las elecciones para presidente del 2022, los colombianos podrán elegir el candidato que en su criterio hará frente a la corrupción en sus regiones y en todo el territorio nacional. Pasada la primera vuelta electoral, podemos visualizar el comportamiento del electorado que anhela erradicar por completo este flagelo, donde según el Índice de la Percepción de la Corrupción – 2021, (Transparency International) Colombia obtuvo 39 puntos sobre 100, siendo 0, corrupción muy elevada y 100 ausencia de corrupción. El país se ubica en el puesto 87 entre 180 países evaluados. Una calificación por debajo de 50 puntos indica niveles de corrupción muy serios en el sector público.
El grado de incertidumbre que viven los colombianos frente al destino del país solo podrá ser contrarrestado con el ejercicio democrático del voto, donde la razón y el intelecto debería empujarnos a realizar una revisión de los planes anticorrupción en los programas de Gobierno.
Concluiremos con un análisis al finalizar el desarrollo, haciendo énfasis en la mezcla del uso de diferentes herramientas para generar algunos insights de valor. Todo esto sin la mínima intención de sesgar o tomar partido político, pues la corrupción es un cáncer y está en nuestras manos intentar hallar una cura en las urnas. También es importante decir que no existe ninguna correlación entre la cantidad de casos encontrados y el ganador de las elecciones en cada región.
📌 Para el tratamiento de los datos obtenidos utilizaré Pandas y Plotly de Python, las visualizaciones serán construidas con la API de MapBox y Tableau Public.
Datos
Los datos principales fueron descargados del informe «Así se mueve la corrupción«, publicado por la ONG Transparencia por Colombia el 2 de diciembre de 2021, donde se presentó el análisis de 967 hechos de corrupción reportados en 2026 notas de prensa nacional publicadas entre 2016 y 2020.

El informe arrojó que la mayoría de hechos de corrupción (53%) se encuentran en: Bogotá (200 hechos), Atlántico (88 hechos), Antioquia (76 hechos), Santander (75 hechos) y Valle del Cauca (74 hechos), donde el tipo de corrupción más frecuente es la administrativa en el sector público.
Utilizando la base de datos del último boletín de los resultados de las elecciones presidenciales de Colombia en primera vuelta para el 2022, emitido por la Registraduría Nacional de Colombia, podemos hacer una comparación con los datos del informe de la corrupción para entender por quiénes votaron en cada ciudad para terminar con este delito.
“Este informe refleja nuevamente el carácter sistemático y estructural de la corrupción. Quienes aspiran a la Presidencia de la República deberán plantear propuestas ambiciosas, decididas y coherentes para enfrentar de manera integral este problema.
Como sociedad debemos hacer una revisión de fondo sobre la profunda afectación que genera la corrupción. Debemos ser capaces de elegir a quienes de manera genuina y seria puedan enfrentar este problema, no comprar discursos facilistas y exigir acciones efectivas. No debemos permitir que nos sigan robando nuestro presente y nuestro futuro”.
Andrés Hernández, Director Ejecutivo, Transparencia por Colombia
METODOLOGÍA
📌 El código completo será publicado en un notebook de Github. Tras un problema con la API de MapBox en el Jupyter Notebook que funcionaba en mi equipo de manera local, decidí tratar los datos en un notebook online de COLAB y después exportar el DataFrame en formato .CSV hacia Tableau Public.
Tratamiento y limpieza de datos
- Importamos nuestras dependencias (pandas, plotly y json) de Python en nuestro notebook.
import pandas as pd
import json
import plotly.express as px
px.set_mapbox_access_token(token_map_plot)
import plotly.graph_objects as go
pd.options.display.max_columns = 999
Visualización del informe «Así se mueve la corrupción»
- Iniciamos la importación de los datos en formato CSV y creamos nuestro primer DataFrame con Pandas en Python.
bd_corr = pd.read_csv('data/base-de-datos-hechos.csv')
- Para este ejemplo debemos tener una cuenta para generar un token con la API de MapBox.
token_map_plot = 'AquíVaTuTokenPersonalDeMapbox'
- El paso a seguir dentro de nuestro EDA será revisar su información, tamaño de columnas y filas, datos nulos, nombres de columnas y tipos de datos a cambiar.
bd_corr.info() #Información del DF
bd_corr.shape #Tamaño en columnas y filas
bd_corr.columns #nombres de columnas
bd_corr.dtypes #tipos de datos a cambiar
- Quise renombrar una de las columnas principales con las que quiero trabajar:
bd_corr = bd_corr.rename(columns={'Tipo de corrupción':'tipo_corrupcion'})
- Agrupo con .groupby en un nuevo DataFrame solamente las columnas que necesito:
map_corr_deptos = bd_corr.groupby(['Departamento', 'Dep_Lat', 'Dep_Lng'])['tipo_corrupcion'].count().reset_index()
Para obtener:

- Aquí me enfrenté a un problema que me tomó varias horas: Las columnas de Dep_Lat y Dep_lng (ubicación de latitud y longitud para cada departamento) cambiaron sus valores desplazando el punto de la coordenada por puntos de miles y millones, es decir:
Para Amazonas devuelve los valores: -42.152.778 y -699.405.556 cuando en realidad sus coordenadas correctas son: -4.215278 y -69.940556
- Intenté mover los puntos desde el notebook con pandas pero no lo logré, finalmente como eran solamente 32 registros decidí descargar el DataFrame en .CSV y darle formato en una hoja de cálculo de Excel. (No debe ser una buena práctica pero hallaré luego la forma correcta de hacerlo ☹ )
map_corr_deptos.to_csv("map_corr_deptos_error.csv")
- Luego cargué de nuevo el CSV corregido en los valores de Latitud y Longitud: (el parámetro «sep=’;’ se utiliza para separar las columnas al cargar el Dataframe con Pandas)
map_corr_deptos_ok = pd.read_csv('data/map_corr_deptos_ok.csv', sep=';')
map_corr_deptos_ok.head()

- Importamos la librería plotly.io para generar nuestra primera visualización:
import plotly.io as pio
pio.templates
fig = px.bar(map_corr_deptos_ok, x='Departamento', y='count',
color='count',
template='plotly_dark',
labels={'count':'Cantidad de casos'},
title='Cantidad de casos de corrupción por departamento',
height=400)
fig.show()

- Hice un cambio en algunos nombres de los departamentos para reducir su longitud:
map_corr_deptos_ok.Departamento = map_corr_deptos_ok.Departamento.replace({'BOGOTÁ, DISTRITO CAPITAL' : 'BOGOTA D.C.'})
map_corr_deptos_ok.Departamento = map_corr_deptos_ok.Departamento.replace({'GUAJIRA' : 'LA GUAJIRA'})
map_corr_deptos_ok.Departamento = map_corr_deptos_ok.Departamento.replace({'NORTE SANTANDER' : 'NORTE DE SAN'})
map_corr_deptos_ok.Departamento = map_corr_deptos_ok.Departamento.replace({'SAN ANDRES, PROV.' : 'SAN ANDRES'})
- Utilicé px.scatter_mapbox para visualizar los datos con el mapa de Colombia:
px.scatter_mapbox(map_corr_deptos_ok,
lat='Dep_Lat',
lon='Dep_Lng',
color='Departamento',
size='tipo_corrupcion',
color_continuous_scale=px.colors.cyclical.IceFire,
#size_max=5,
zoom=4,
center = dict(
lat = 4.570868,
lon = -74.297333
),
height= 600
)

- Y otro modo de visualización aplicando un estilo diferente de MapBox:
fig = go.Figure(go.Scattermapbox(
lon = map_corr_deptos_ok.Dep_Lng,
lat = map_corr_deptos_ok.Dep_Lat,
mode = 'markers+text',
marker = go.scattermapbox.Marker(size=map_corr_deptos_ok.tipo_corrupcion,
color = map_corr_deptos_ok.tipo_corrupcion,
#colorscale = 'Edge',
showscale = True,
sizemode = 'area',
opacity = 0.8
),
hoverinfo = 'text',
hovertext =
'<b>Departamento</b>: '+ map_corr_deptos_ok['Departamento'].astype(str) + '<b>' +
'<b>Cantidad de actos</b>: '+ map_corr_deptos_ok['tipo_corrupcion'].astype(str) + '<b>'
))
fig.update_layout(
hovermode = 'x',
margin = dict(r=0, l=0, b=0, t=0),
mapbox = dict(
accesstoken = token_map_plot,
style = 'dark',
zoom = 4.5,
center = dict(
lat = 4.570868,
lon = -74.297333
)
),
showlegend = True,
autosize = True
)

Visualización del mapa electoral en primera vuelta presidencial en Colombia 2022 🗳
- Importamos la data desde nuestro archivo CSV:
df_elecciones = pd.read_csv('data/resultados_primera_vuelta_2022_boletin_68.csv')
- Analizamos su contenido en nombres de columnas (.columns), cantidad de datos (.shape) y tipos de datos (.dtypes)
- Con el dataFrame df_elecciones podemos visualizar las votaciones dentro y fuera de Colombia, por ejemplo en Francia 🇫🇷 estos fueron los resultados: False= Votos totales // True=Votos en Francia por cada candidato (4 primeros):
df_elecciones_francia = df_elecciones.groupby([df_elecciones.mun == 'FRANCIA'])['FEDERICO_GUTIÉRREZ_vot', 'RODOLFO_HERNÁNDEZ_vot', 'GUSTAVO_PETRO_vot', 'SERGIO_FAJARDO_vot'].sum().reset_index()
df_elecciones_francia.head()

df_elecciones_francia.plot(kind='bar')

- Agrupé un nuevo DataFrame con .groupby los departamentos y los 4 candidatos con más votaciones.
df_elecciones_deptos = df_elecciones.groupby(['dpto'])['FEDERICO_GUTIÉRREZ_vot', 'RODOLFO_HERNÁNDEZ_vot', 'GUSTAVO_PETRO_vot', 'SERGIO_FAJARDO_vot'].sum().reset_index()

- Hice un gráfico de barras con matplotlib (pero necesita más formato):
df_elecciones_deptos.plot(kind='bar')

- Aquí la primera gráfica de barras de los votos de cada candidato por departamento:
fig = px.bar(df_elecciones_deptos, x='dpto', y='Nombre_Columna_Candidato',
color='dpto',
template='plotly_dark',
labels={'df_elecciones_deptos':'Cantidad de votos'},
title='Cantidad de votos por departamento',
height=400)
fig.show()




- Finalmente para conocer el resultado de las votaciones en las ciudades con más casos de corrupción unifiqué con .merge los dos Dataframes (df_elecciones_deptos y map_coo_deptos_ok) en un solo Dataframe = df_elecciones_casos, con este Dataframe estamos adicionando las coordenadas geográficas y la cantidad de casos de corrupción por departamento.
df_elecciones_casos = df_elecciones_deptos.merge(map_corr_deptos_4, left_on='dpto', right_on='Departamento', how ='left')
df_elecciones_casos
- Analizando el tipo de datos del nuevo Dataframe vemos que la columna «tipo_corrupción» cambio a tipo Float64 y necesitamos que sea tipo entero «Int».
df_elecciones_casos.tipo_corrupcion = df_elecciones_casos.tipo_corrupcion.astype(int)
- Ahora tenemos listo nuestro Dataframe para ser exportado como CSV y seguir probando algunas posibilidades en Tableau Public.
df_elecciones_casos.to_csv("data/df_elecciones_casos_filtrado.csv")
Tableau Public

Con los datos unificados en formato .CSV, utilicé la plataforma de Tableau Public para realizar un dashboard que reuniera algunas visualizaciones que nos apoyen en el análisis.
📌 Pueden acceder al dashboard público en este enlace.
Análisis y conclusiones

A pesar que se identificaron casos de corrupción en los 32 departamentos y Bogotá como Distrito Capital, es importante resaltar que el 53% tienen concentración en solo cinco departamentos: Bogotá, Atlántico, Antioquia, Santander y Valle del Cauca.
Con los 200 casos de corrupción concentrados en Bogotá, se remarca el hecho de la centralización de instituciones, organismos públicos y actores sociales y económicos, al igual que la facilidad para denunciar, pues dentro del informe se hace referencia a las garantías de la libertad de expresión y la existencias de medios de comunicación. Esto último, refleja el bajo reporte en algunas regiones no por inexistencia de casos de corrupción sino por la falta del ejercicio libre del periodismo investigativo, sumado a las amenazas, terrorismo y a la misma corrupción.
El resultado de cruzar los datos de corrupción por departamento y el resultado electoral presidencial en primera vuelta se traduce simplemente en la confirmación de las tendencias hacia los candidatos que eligieron los colombianos en cada departamento. Gustavo Petro fue el ganador en Bogotá, Atlántico y Valle del Cauca, Federico Gutiérrez ganador en Antioquia y Rodolfo Hernández en Santander.

Lejos de realizar un análisis político, existe una fuerte tendencia hacia un cambio determinante en la forma de gobernar a Colombia, se genera mucha polarización de cara hacia los ganadores que irán a segunda vuelta el 19 de junio de 2022: Gustavo Petro y Rodolfo Hernández.
Muchos siguen convocando a los NO VOTANTES a participar activamente en esta decisión tomando partido con argumentos y conocimiento de las propuestas, no con memes o noticias falsas. La indiferencia en el abstencionismo duele más al saber que todo puede mejorar si nos ponemos de acuerdo para ir hacia el mismo objetivo y erradicando por completo la corrupción que tanto nos duele como pueblo.
Hallé el camino de los datos para contar historias visuales, la curva de aprendizaje es muy fuerte, a veces frustrante, encontrándome con problemas todo el tiempo, publico y pido ayuda, a veces llega y a veces no, a veces la solución está en StackOverflow, a veces en Youtube o en algún tutorial en Medium, pero confieso que me encanta y me gustaría aprender a hacerlo mejor.
Este proyecto lo hago a 4 días de las elecciones presidenciales en segunda vuelta, todos los que tenemos la oportunidad de elegir deberíamos hacerlo. Un voto hace la diferencia.

Consulte el código en Python de todo el proyecto en el repositorio de GitHub
Referencias
- https://www.elespectador.com/politica/elecciones-colombia-2022/la-corrupcion-sigue-siendo-la-mayor-preocupacion-de-los-colombianos-invamer/
- https://transparenciacolombia.org.co/2022/01/25/indice-de-percepcion-de-la-corrupcion-2021/
- https://www.elespectador.com/politica/elecciones-colombia-2022/la-corrupcion-sigue-siendo-la-mayor-preocupacion-de-los-colombianos-invamer/

