DEV Community

Cover image for 10.430 muertes, 10 preguntas y un pipeline en Python: lo que los datos de violencia policial en EE.UU. no te cuentan a simple vista
David Naranjo Ramírez for Evolve

Posted on

10.430 muertes, 10 preguntas y un pipeline en Python: lo que los datos de violencia policial en EE.UU. no te cuentan a simple vista

Cuando el Washington Post empezó a contar los muertos en 2015, el FBI subestimaba casi el 50% de los casos. Ese dato me enganchó. No por el morbo, sino por lo que implica metodológicamente: si los registros oficiales fallan de manera tan estrepitosa, ¿qué más se pierde cuando no miras bien los datos?

Ese fue el punto de partida de EDAFatalForce, mi proyecto de Análisis Exploratorio de Datos del Máster de Data Science en Evolve.


El dataset: periodismo de datos como fuente primaria

El core del proyecto es la base de datos Fatal Force del Washington Post — 10.430 incidentes fatales entre 2015 y 2024 con variables como raza, edad, armamento, comportamiento de fuga, nivel de amenaza percibida y si el agente llevaba cámara corporal.

Para enriquecerlo crucé tres fuentes:

  • Census Bureau ACS 2020 — datos socioeconómicos de 3.221 condados (ingresos, pobreza, desempleo)
  • NCSL — políticas de cámara corporal por estado
  • Tabla FIPS — para enlazar condados con el Census

El mayor desafío no fue el modelado. Fue la calidad del dato. El 45% de los registros no tenía condado, lo que bloqueaba cualquier join con el Census. La solución: construir internamente un mapa ciudad + estado → condado usando la moda de los registros que sí lo tenían. Resultado: de 45% de nulos a 17,4%. Un cambio que desbloqueó más de 2.800 filas para el análisis socioeconómico.


El proceso: bugs, fixes y un pipeline modular

El proyecto está estructurado como un pipeline reproducible en src/: limpieza → enriquecimiento → feature engineering → EDA. Un solo python main.py lo ejecuta todo, incluyendo la descarga del Census.

Durante la auditoría encontré dos bugs críticos en el feature engineering que hubieran invalidado análisis completos:

Bug 1 — La paradoja de la fuga estaba rota. El valor raw "not" (53% de los registros) no coincidía con la regex diseñada para mapear "no huía", así que más de 5.500 víctimas que no huían quedaban clasificadas como comportamiento desconocido. La pregunta Q2 entera era inválida.

Bug 2 — "Undetermined" contaba como armado. Los 463 registros con armamento "undetermined" heredaban is_armed = 1.0 por caer en el default del np.select. Víctimas con armamento desconocido aparecían como armadas en todas las tasas.

Ambos fixes son de una línea. El impacto analítico, considerable.


Resultados: lo que los datos dicen y lo que no

Diez preguntas, diez respuestas con tests estadísticos. Las más reveladoras:

El ranking de estados respecto a número de incidentes fatales cambia por completo al normalizar. California lidera con +1200 incidentes brutos. Pero al dividir por población, Misisipi sube al primer puesto con 85,5 casos por 100.000 habitantes. El volumen engaña. La tasa informa.

Los protocolos de crisis mental funcionan. Los incidentes con signos de enfermedad mental presentan una tasa de amenaza letal del 35,3% frente al 44,4% del resto (χ²=55,18, p<0,001). El resultado más robusto estadísticamente de todo el análisis, y el más contraintuitivo.

Huir en coche es más peligroso que no huir. La tasa de amenaza letal resulta 4 puntos y medio porcentuales mayor en persecuciones vehiculares que en personas que no huyen. Un vehículo a alta velocidad es percibido como amenaza física directa, no solo como evasión.

Entre víctimas desarmadas, la raza sigue siendo predictora. Las víctimas negras desarmadas tienen una tasa letal 4,2 puntos superior a las blancas (χ²=11,65, p=0,003). threat_level es la narrativa del agente, no un hecho verificado — esa limitación es parte del análisis, no una nota al pie.


Lo que aprendí

Que los bugs de feature engineering son los más peligrosos porque no rompen el código — producen resultados plausibles pero incorrectos. Y que documentar las limitaciones no debilita un análisis: lo hace honesto y, paradójicamente, más creíble.

Si lo repitiera, integraría coordenadas lat/lon para análisis espaciales con DBSCAN geográfico. Los hotspots por condado cuentan la mitad de la historia; los hotspots dentro del condado contarían la otra.


📁 Repo completo en GitHub: https://github.com/dnarram/Proyecto-Master-DataScience-Evolve-DavidNaranjoRamirez-EDAFatalForce


Proyecto desarrollado durante el Máster en Data Science de Evolve.

Top comments (0)