Índice

1Introducción y resumen ejecutivo ObjetivoIndicadoresHallazgosDescripción general
2Contexto y descripción de los datos Origen y estructuraVariables principalesNombres de columnasResumen estadístico
3Análisis de indicadores 3.1 Día y tipo de vehículo3.2 Evolución diaria3.3 Género o titular3.4 Valor por infracción3.5 Comparendos por mes3.6 Personas con más comparendos
4Resultados por consulta Consulta 1: infracción y vehículoConsulta 2: propietario y vehículoConsulta 3: valor por propietarioConsulta 4: top 10 de propietariosConsulta 5: identificación y géneroConsulta 6: evolución en el tiempo
5Hallazgos y conclusiones Hallazgos principalesConclusión general
6Recomendaciones Calidad de los datosGestión y controlPolítica pública
7Referencias Fuente de datosHerramientas
Centro de Gestión y Servicios para el Tránsito

Informe de Gestión Vial:
Análisis de Comparendos
Barranquilla · Abril – Mayo 2010

Analítica de Datos · SENA

Una mirada a las infracciones de tránsito, su frecuencia, impacto económico y comportamiento en el tiempo.

Período de análisis: 12/04/2010 a 27/05/2010
Neider Peñaranda · TAD-13 · 30/10/2026
1

Introducción y resumen ejecutivo

Objetivo

Este informe aplica herramientas estadísticas básicas en R al análisis de los comparendos de tránsito impuestos en Barranquilla entre el 12/04/2010 y el 27/05/2010. Se exploran, describen y visualizan los datos para identificar patrones, tendencias y relaciones relevantes, mediante medidas de frecuencia, concentración y evolución en el tiempo, que apoyen la toma de decisiones en la gestión del tránsito.

Cómo usar este informe

Pasa el cursor sobre cualquier gráfico para leer sus datos exactos. Cada gráfico se dibuja al llegar a él, y el botón «↻ Repetir» lo anima de nuevo. El botón «Ocultar código» (arriba a la derecha) muestra u oculta el código en R de todo el informe.

Indicadores

2.119
Registros
25
Columnas
2
Tipos de vehículo
4
Infracciones
$ 643.698.500
Valor total
1.250
Total en SMLV 2010
Hallazgos

La base tiene buena integridad (0 valores vacíos), pero se detectaron 1 fila duplicada exacta y 17 números de comparendo repetidos con distinto mandamiento. Fueron depurados o señalados para garantizar la calidad del análisis.

Descripción general

La base reúne comparendos aplicados a conductores y propietarios de vehículos en Barranquilla (Atlántico). Cada registro incluye datos del infractor (nombre, género, tipo y número de identificación), del vehículo (placa y tipo), de la infracción (código y nombre), la fecha del comparendo desglosada en día, mes y año, y el valor a pagar. En total tiene 25 columnas y 2.120 registros originales (2.119 tras la depuración), lo que permite un análisis estadístico descriptivo sólido.

2

Contexto y descripción de los datos

Origen y estructura

La información proviene de la base de comparendos de tránsito con 25 variables originales sobre el infractor, la infracción, la fecha, el vehículo y el valor económico del comparendo. A continuación se muestra el código con el que se leyó y depuró la base.

# Lectura y depuración de la base
raw   <- read_excel(ruta, sheet = "BD Comparendos OK")  # lee la hoja 'BD Comparendos OK' del Excel
n_raw <- nrow(raw)  # guarda el número de filas originales
datos <- raw %>% select(-starts_with("#")) %>% distinct() %>% janitor::clean_names()  # quita columnas que empiezan con '#', elimina filas duplicadas y estandariza nombres de columnas
n_dup <- n_raw - nrow(datos)  # calcula cuántas filas duplicadas se eliminaron
datos <- datos %>% mutate(  # crea y corrige columnas
  ejecutado  = ejecutado %>% str_squish() %>% str_replace_all("G\\.M\\.A\\.C\\.", "GMAC"),  # propietario: quita espacios sobrantes y unifica 'G.M.A.C.' como 'GMAC'
  tipo_id    = recode(tipo_de_identificacion, "Cedula de Ciudadanía" = "Cédula de ciudadanía",  # tipo de identificación: corrige las etiquetas
                      "Cedula de Extanjería" = "Cédula de extranjería", "Nit" = "NIT"),  # (continúa) etiqueta de extranjería y NIT
  infraccion = str_to_sentence(nom_infraccion) %>% str_replace("maxima", "máxima"),  # infracción: texto en formato oración y corrige la tilde de 'máxima'
  fecha      = as.Date(fecha_de_comparendo),  # fecha: convierte a tipo Date
  smlv       = costo_de_comparendo / smlv_2010,  # valor del comparendo expresado en SMLV de 2010
  dia        = factor(str_to_title(nom_dia), levels = c("Lunes","Martes","Miércoles","Jueves","Viernes","Sábado","Domingo")),  # día de la semana como factor ordenado (lunes a domingo)
  mes        = factor(str_to_title(nom_mes), levels = c("Abril", "Mayo")),  # mes como factor ordenado (abril, mayo)
  vehiculo   = str_to_title(vehiculo))  # tipo de vehículo en formato título (Auto, Moto)
# Resumen de la base y variables principales
resumen <- tibble(Indicador = c("Registros (base depurada)", "Columnas originales", "Valores vacíos", "Filas duplicadas exactas",  # tabla resumen: nombres de los indicadores
                                "Comparendos únicos", "Propietarios únicos", "Placas únicas", "Período"),  # (continúa los indicadores)
                  Valor = c(fm(nrow(datos)), ncol(raw), sum(is.na(raw)), n_dup, fm(n_distinct(datos$comparendo)),  # valores de cada indicador: registros, columnas, vacíos y duplicados
                            fm(n_distinct(datos$ejecutado)), fm(n_distinct(datos$placa_de_vehiculo)), paste(f_ini, "a", f_fin)))  # (continúa: únicos y período)
vars <- c("Tipo de vehículo", "Infracción", "Fecha del comparendo", "Valor del comparendo (COP y SMLV)", "Tipo de identificación", "Propietario (ejecutado)", "Género")  # lista de variables principales
salida('<div class="dos-col">', tabla_html(resumen), '<div class="vars" id="o2"><b>Variables principales</b><ul>', paste0("<li>", vars, "</li>", collapse = ""), '</ul></div></div>')  # imprime en dos columnas la tabla resumen y la caja de variables
Indicador Valor
Registros (base depurada) 2.119
Columnas originales 25
Valores vacíos 0
Filas duplicadas exactas 1
Comparendos únicos 2.102
Propietarios únicos 1.247
Placas únicas 1.457
Período 12/04/2010 a 27/05/2010
Variables principales
  • Tipo de vehículo
  • Infracción
  • Fecha del comparendo
  • Valor del comparendo (COP y SMLV)
  • Tipo de identificación
  • Propietario (ejecutado)
  • Género
Depuración de datos

Se eliminó 1 fila duplicada, se unificaron nombres (p. ej. G.M.A.C. por GMAC), se corrigieron etiquetas y se convirtió el valor a SMLV de 2010 ($ 515.000). Cada comparendo vale 0,1, 0,5 o 1 SMLV.

Aplicación de funciones: colnames()

Lo primero es identificar los nombres de las columnas para poder llamarlas correctamente en el análisis.

# Nombres de las columnas originales
cat(paste0('<span class="tag">', str_squish(colnames(raw)), '</span>', collapse = ""))  # imprime cada nombre de columna como una etiqueta

No. MANDAMIENTO DE PAGOFECHA MANDAMIENTO DE PAGOEJECUTADOTIPO DE IDENTIFICACIONNo. IDENTIFICACION#TIPO DE IDENTIFICACIONGENERO# GENEROCOD. INFRACCION# COD. INFRACCIONNOM.INFRACCION#NOM. INFRACCIONCOMPARENDOFECHA DE COMPARENDOAÑOMESNOM MES# NOM. MESDIANOM DIA# NOM. DiaPLACA DE VEHICULOVEHICULO#VEHICULOCOSTO DE COMPARENDO

Aplicación de funciones: resumen estadístico

Resumen general de la fecha y del valor a pagar, para revisar la distribución y los cuartiles.

# Resumen estadístico (mínimo, cuartiles, mediana, media y máximo)
fq <- as.numeric(datos$fecha); vq <- datos$costo_de_comparendo  # fechas y valores como números para calcular cuartiles
est <- tibble(`Estadístico` = c("Mínimo", "1.er cuartil", "Mediana", "Media", "3.er cuartil", "Máximo"),  # tabla de estadísticos: nombres de las filas
              `Fecha del comparendo` = format(as.Date(unname(c(min(fq), quantile(fq, .25), median(fq), mean(fq), quantile(fq, .75), max(fq))), origin = "1970-01-01"), "%d/%m/%Y"),  # mínimo, cuartiles, mediana, media y máximo de la fecha
              `Valor del comparendo` = cop(unname(c(min(vq), quantile(vq, .25), median(vq), mean(vq), quantile(vq, .75), max(vq)))))  # mínimo, cuartiles, mediana, media y máximo del valor
salida(tabla_html(est))  # imprime la tabla
Estadístico Fecha del comparendo Valor del comparendo
Mínimo 12/04/2010 $ 51.500
1.er cuartil 27/04/2010 $ 257.500
Mediana 06/05/2010 $ 257.500
Media 05/05/2010 $ 303.775
3.er cuartil 16/05/2010 $ 257.500
Máximo 27/05/2010 $ 515.000
3

Análisis de indicadores

3.1 Comparendos por día de la semana y tipo de vehículo

Cómo entender este gráfico

Qué muestra: cuántos comparendos se impusieron cada día de la semana, separados entre autos (azul) y motos (coral).

Cómo leerlo: cada columna es un día; su altura es el total de comparendos y el número en negrita sobre ella es ese total. La parte azul de la columna son los autos y la coral las motos.

Al pasar el cursor: al situarte sobre un día aparece el detalle de autos, motos y el total de ese día.

Para qué sirve: identificar los días con más infracciones para programar operativos de control en esos momentos.

# Barras apiladas por día (autos y motos) con el total encima
d_dia <- datos %>% count(dia, vehiculo) %>%  # cuenta comparendos por día y vehículo
  mutate(dia = as.character(dia), tip = paste0(vehiculo, ": ", fm(n), " comparendos"))  # convierte el día a texto y arma el texto del hover
tot_dia <- datos %>% count(dia) %>%  # total de comparendos por día
  mutate(dia = as.character(dia), tip = paste0("<b>Total: ", fm(n), " comparendos</b>"))  # texto del hover con el total
p <- plot_ly(height = 460)  # crea el gráfico plotly vacío (alto 460 px)
for (veh in names(col_veh)) {  # para cada tipo de vehículo...
  p <- add_bars(p, data = filter(d_dia, vehiculo == veh), x = ~dia, y = ~n, name = veh,  # agrega una serie de barras con su color
                marker = list(color = col_veh[[veh]]), hoverinfo = "text", hovertext = ~tip)  # (continúa: color y hover)
}  # fin del for
p <- p %>%  # continúa el gráfico con %>%
  add_trace(data = tot_dia, x = ~dia, y = ~n, type = "scatter", mode = "text", text = ~fm(n),  # agrega capa de texto con el total sobre cada columna
            textposition = "top center", textfont = list(size = 15, color = pal$marino),  # (posición y estilo del texto)
            showlegend = FALSE, hoverinfo = "text", hovertext = ~tip) %>%  # (sin leyenda; hover propio)
  layout(barmode = "stack", hovermode = "x unified",  # barras apiladas y hover unificado por día
         xaxis = eje_cat(levels(datos$dia)), yaxis = eje_val(max(tot_dia$n) * 1.18)) %>%  # (continúa: ejes con días en orden y rango del eje vertical)
  pl("Comparendos por día de la semana")  # aplica el estilo común y el título
graf(p)  # muestra el gráfico dentro de la tarjeta
Dato a resaltar

Sábado y domingo concentran el 36,2% de los comparendos; el día con más registros es el domingo (396). Los autos representan el 91,4% del total.

3.2 Evolución diaria de los comparendos

La variación diaria permite detectar días atípicos, eventos especiales o aumentos asociados a operativos específicos, clima, festivos o tráfico inusual. El patrón temporal sirve para prever puntos críticos y ajustar los operativos de tránsito.

Cómo entender este gráfico

Qué muestra: el número de comparendos de cada fecha entre abril y mayo, como una línea con el área sombreada debajo.

Cómo leerlo: el eje horizontal son las fechas (una marca por semana) y el vertical la cantidad de comparendos de ese día. Los tres puntos coral con número son los días con más registros.

Al pasar el cursor: sobre cualquier punto de la línea aparecen la fecha, el día de la semana y los comparendos de ese día.

Para qué sirve: ver en qué fechas se disparan las infracciones y reconocer días atípicos, como operativos, festivos o puentes.

# Línea con área y los 3 días pico resaltados
diario <- datos %>% count(fecha, dia) %>%  # comparendos por fecha y día de la semana
  mutate(tip = paste0("<b>", dia, " ", format(fecha, "%d/%m/%Y"), "</b><br>", fm(n), " comparendos"))  # texto del hover
picos <- diario %>% slice_max(n, n = 3, with_ties = FALSE)  # los 3 días con más comparendos
p <- plot_ly(height = 440) %>%  # inicia el gráfico plotly
  add_trace(data = diario, x = ~fecha, y = ~n, type = "scatter", mode = "lines+markers",  # línea con marcadores y área sombreada
            fill = "tozeroy", fillcolor = "rgba(20,184,166,.20)", name = "Comparendos",  # relleno hasta cero, color y nombre
            line = list(color = pal$turquesa, width = 3), marker = list(color = pal$turquesa, size = 6),  # estilo de línea y marcadores
            hoverinfo = "text", hovertext = ~tip) %>%  # hover
  add_trace(data = picos, x = ~fecha, y = ~n, type = "scatter", mode = "markers+text", name = "Días pico",  # capa de los días pico (puntos coral con número)
            text = ~n, textposition = "top center", textfont = list(color = pal$coral, size = 15),  # texto sobre los puntos
            marker = list(color = pal$coral, size = 13, line = list(color = "white", width = 2)),  # estilo del marcador con borde blanco
            hoverinfo = "text", hovertext = ~tip) %>%  # hover
  layout(xaxis = list(title = "", type = "date", tickformat = "%d/%m", dtick = 7 * 24 * 3600 * 1000,  # eje x como fecha con una marca por semana
                      tick0 = as.character(min(diario$fecha)), gridcolor = "#E5EAF2", fixedrange = TRUE),  # (continúa: inicio de la marca semanal y cuadrícula)
         yaxis = eje_val(max(diario$n) * 1.25)) %>%  # eje y con rango hasta 1,25 × el máximo
  pl("Comparendos por fecha de infracción")  # estilo y título
graf(p)  # muestra el gráfico

3.3 Comparendos por género o tipo de titular

Se cuenta la cantidad de comparendos según el género del infractor o si el titular es una empresa.

Cómo entender este gráfico

Qué muestra: cuántos comparendos corresponden a mujeres, hombres, empresas y cédulas nuevas.

Cómo leerlo: cada columna es una categoría; encima aparece la cantidad de comparendos y, entre paréntesis, el porcentaje que representa del total. Las columnas van de la más alta a la más baja.

Al pasar el cursor: sobre una columna aparecen la categoría, la cantidad y su porcentaje del total.

Para qué sirve: saber quién concentra las infracciones y si conviene diferenciar las estrategias entre personas naturales y empresas.

# Barras por género con cantidad y porcentaje
gen <- datos %>% count(genero = str_to_title(genero)) %>% mutate(p = n / sum(n)) %>% arrange(desc(n)) %>%  # cuenta comparendos por género y calcula la proporción; ordena de mayor a menor
  mutate(txt = paste0(fm(n), "<br>(", pct(p), ")"),  # texto sobre la barra: cantidad y porcentaje
         tip = paste0("<b>", genero, "</b><br>", fm(n), " comparendos<br>", pct(p), " del total"),  # texto del hover
         col = unname(col_gen[genero]))  # color de cada categoría
p <- plot_ly(gen, x = ~genero, y = ~n, type = "bar", marker = list(color = gen$col),  # gráfico de barras por género
             text = ~txt, textposition = "outside", cliponaxis = FALSE,  # texto exterior sobre las barras
             textfont = list(size = 15, color = pal$marino),  # tamaño y color del texto
             hoverinfo = "text", hovertext = ~tip, height = 440) %>%  # hover y alto
  layout(xaxis = eje_cat(gen$genero), yaxis = eje_val(max(gen$n) * 1.3)) %>%  # ejes: categorías ordenadas y rango del eje y
  pl("Distribución de comparendos por género o empresa", leyenda = FALSE)  # estilo y título (sin leyenda)
graf(p)  # muestra el gráfico
Lectura

La categoría con más comparendos es «Mujer» (45,7%). Las empresas aportan el 22,0% de los comparendos, lo que indica la necesidad de fortalecer el control sobre las flotas vehiculares corporativas y de diferenciar las estrategias entre personas naturales y jurídicas.

3.4 Valor económico por tipo de infracción

Se suman los valores de los comparendos agrupados por la infracción cometida. Es el valor impuesto, no el recaudo efectivo, porque la base no trae fechas de pago.

Cómo entender este gráfico

Qué muestra: cuánto dinero suman los comparendos de cada tipo de infracción.

Cómo leerlo: cada barra horizontal es una infracción y su longitud es el valor total en pesos. A la derecha se ve el monto y, entre paréntesis, el porcentaje del valor total. Van ordenadas de mayor a menor.

Al pasar el cursor: sobre una barra aparecen el nombre completo de la infracción, su valor, su participación y el número de comparendos.

Para qué sirve: priorizar las infracciones que más pesan en el valor total, que no siempre son las más frecuentes.

# Barras horizontales del valor económico por infracción
inf_v <- datos %>% group_by(infraccion) %>% summarise(v = sum(costo_de_comparendo), n = n(), .groups = "drop") %>%  # valor y número de comparendos por infracción
  arrange(desc(v)) %>% mutate(p = v / sum(v))  # ordena de mayor a menor y calcula el porcentaje del valor total
inf_g <- inf_v %>% arrange(v) %>%  # ordena de menor a mayor para que la mayor quede arriba
  mutate(et = wrapbr(infraccion, 28), txt = paste0(cop(v), "  (", pct(p), ")"),  # etiqueta con saltos de línea, texto de la barra y hover
         tip = paste0("<b>", infraccion, "</b><br>Valor: ", cop(v), "<br>Participación: ", pct(p), "<br>Comparendos: ", fm(n)))  # (continúa el hover)
p <- plot_ly(inf_g, x = ~v, y = ~et, type = "bar", orientation = "h", marker = list(color = pal$coral),  # barras horizontales del valor por infracción
             text = ~txt, textposition = "outside", cliponaxis = FALSE,  # texto exterior en las barras
             textfont = list(size = 14, color = pal$marino),  # tamaño y color del texto
             hoverinfo = "text", hovertext = ~tip, height = 430) %>%  # hover y alto
  layout(xaxis = eje_val(max(inf_g$v) * 1.65, showticklabels = FALSE, showgrid = FALSE),  # eje x sin números ni cuadrícula, con espacio para el texto
         yaxis = eje_cat(inf_g$et)) %>%  # eje y con las infracciones en orden
  pl("Valor económico de los comparendos por infracción", leyenda = FALSE)  # estilo y título
graf(p)  # muestra el gráfico
Lectura

«Velocidad superior a la máxima permitida» aporta $ 418.695.000 (65,0%), lo que indica alta frecuencia y sanción elevada. Le sigue «No detenerse ante una luz roja o amarilla» con $ 197.760.000. Entre las dos suman el 95,8% del valor total; «Transitar en sentido contrario» tiene un valor mínimo, por su baja ocurrencia o menor detección.

3.5 Comparendos por mes

Se agrupan los comparendos por el mes en que ocurrieron para revisar la variación mensual.

Cómo entender este gráfico

Qué muestra: el total de comparendos de abril y de mayo.

Cómo leerlo: la altura de cada columna es el total del mes; encima aparece ese total y el promedio de comparendos por día. Abril empieza el 12/04, así que tiene menos días y conviene comparar con el promedio diario, no con el total.

Al pasar el cursor: sobre una columna aparecen el total, los días con registros, el promedio diario y el valor del mes.

Para qué sirve: comparar los dos meses de forma justa y ver si la actividad aumentó o bajó.

# Barras de comparendos por mes con promedio diario
mes_t <- datos %>% group_by(mes) %>% summarise(n = n(), dias = n_distinct(fecha), v = sum(costo_de_comparendo), .groups = "drop") %>%  # por mes: comparendos, días con registros y valor
  mutate(prom = n / dias, mes = as.character(mes),  # promedio diario y mes como texto
         txt = paste0("<b>", fm(n), " comparendos</b><br>", format(round(prom, 1), decimal.mark = ","), " por día"),  # texto sobre la barra
         tip = paste0("<b>", mes, "</b><br>", fm(n), " comparendos<br>", dias, " días con registros<br>",  # texto del hover
                      format(round(prom, 1), decimal.mark = ","), " por día<br>Valor: ", cop(v)))  # (continúa el hover)
p <- plot_ly(mes_t, x = ~mes, y = ~n, type = "bar",  # gráfico de barras por mes
             marker = list(color = unname(c(Abril = pal$azul, Mayo = pal$turquesa)[mes_t$mes])),  # color de cada mes
             text = ~txt, textposition = "outside", cliponaxis = FALSE, textfont = list(size = 15, color = pal$marino),  # texto exterior
             hoverinfo = "text", hovertext = ~tip, height = 430) %>%  # hover y alto
  layout(xaxis = eje_cat(mes_t$mes), yaxis = eje_val(max(mes_t$n) * 1.3), bargap = 0.5) %>%  # ejes y separación entre barras
  pl("Comparendos por mes", leyenda = FALSE)  # estilo y título
graf(p)  # muestra el gráfico
Lectura

Mayo registra 1.408 comparendos frente a 711 de abril (98% más). Pero abril solo cubre 19 días (desde el 12/04/2010) y mayo 27, así que la comparación justa es el promedio diario: 37,4 frente a 52,1 (39% más).

3.6 Personas naturales con más comparendos

Se identifican las 10 personas con más comparendos registrados, excluyendo empresas (se incluyen los empates en el último lugar).

Cómo entender este gráfico

Qué muestra: las personas naturales (sin empresas) con mayor número de comparendos acumulados.

Cómo leerlo: cada barra horizontal es una persona y el número a la derecha es su cantidad de comparendos. La de arriba es la que más acumula.

Al pasar el cursor: sobre una barra aparecen el nombre, la cantidad de comparendos y el valor acumulado.

Para qué sirve: reconocer a los reincidentes para enfocar campañas educativas y acciones sancionatorias en ellos.

# Top 10 de personas naturales por número de comparendos
pers_all <- datos %>% filter(str_to_upper(genero) != "EMPRESA") %>%  # comparendos por propietario, sin empresas
  group_by(ejecutado) %>% summarise(n = n(), v = sum(costo_de_comparendo), .groups = "drop")  # (continúa: agrupa y suma)
pers <- pers_all %>% slice_max(n, n = 10, with_ties = TRUE) %>% arrange(n) %>%  # top 10 (con empates) ordenado de menor a mayor
  mutate(et = wrapbr(ejecutado, 45),  # etiqueta con saltos de línea
         tip = paste0("<b>", ejecutado, "</b><br>", n, " comparendos<br>Valor: ", cop(v)))  # texto del hover
p <- plot_ly(pers, x = ~n, y = ~et, type = "bar", orientation = "h", marker = list(color = pal$violeta),  # barras horizontales de las personas
             text = ~n, textposition = "outside", cliponaxis = FALSE, textfont = list(size = 14, color = pal$marino),  # texto exterior
             hoverinfo = "text", hovertext = ~tip, height = 120 + 40 * nrow(pers)) %>%  # hover y alto proporcional al número de barras
  layout(xaxis = eje_val(max(pers$n) * 1.15, tickformat = "d"), yaxis = eje_cat(pers$et), bargap = 0.3) %>%  # ejes y separación
  pl("Top 10 de personas naturales con más comparendos", leyenda = FALSE)  # estilo y título
graf(p)  # muestra el gráfico
Lectura

La persona natural con más comparendos acumula 27, frente a 10 de la siguiente. Hay 289 personas naturales con 2 o más comparendos. Identificar a los reincidentes permite focalizar intervenciones educativas y sancionatorias más precisas.

4

Resultados por consulta

Consulta 1. Frecuencia de infracciones según el tipo de vehículo

Cómo entender este gráfico

Qué muestra: a la izquierda, qué porcentaje de los comparendos corresponde a autos y a motos; a la derecha, cuántos comparendos hay de cada infracción, separados por tipo de vehículo.

Cómo leerlo: en la dona, cada color es un tipo de vehículo, el porcentaje va dentro del anillo y el total de registros, en el centro. En las barras, la longitud es la cantidad de comparendos y los colores indican cuánto aporta cada vehículo.

Al pasar el cursor: en la dona aparecen el vehículo, la cantidad y el porcentaje; en las barras, la infracción completa y los comparendos de cada vehículo.

Para qué sirve: ver qué vehículo infringe más y en cuáles infracciones pesan más los autos o las motos.

# Dona de participación por vehículo + barras por infracción
q1 <- datos %>% count(vehiculo) %>% mutate(p = n / sum(n))  # comparendos y proporción por vehículo
p_dona <- plot_ly(q1, labels = ~vehiculo, values = ~n, type = "pie", hole = 0.58, sort = FALSE,  # dona: etiquetas, valores, tipo pie y hueco central
                  direction = "clockwise", textinfo = "percent",  # sentido horario y texto en porcentaje
                  textfont = list(color = "white", size = 17),  # texto blanco
                  marker = list(colors = unname(col_veh[q1$vehiculo]), line = list(color = "white", width = 3)),  # colores por vehículo con borde blanco
                  hovertemplate = "<b>%{label}</b><br>%{value:,.0f} comparendos<br>%{percent:.1%}<extra></extra>",  # texto del hover
                  height = 460) %>%  # alto del gráfico
  layout(annotations = list(list(text = paste0("Total<br><b>", fm(sum(q1$n)), "</b>"), x = 0.5, y = 0.5,  # texto central con el total
                                 showarrow = FALSE, font = list(size = 18, color = pal$marino)))) %>%  # (continúa: sin flecha, tamaño y color)
  pl("Participación por vehículo", margen = list(t = 70, r = 10, b = 20, l = 10)) %>%  # estilo y título
  layout(legend = list(orientation = "h", x = 0.5, xanchor = "center", y = -0.02))  # leyenda horizontal centrada bajo la dona

q1b <- datos %>% count(infraccion, vehiculo) %>%  # comparendos por infracción y vehículo
  mutate(et = wrapbr(infraccion, 24), tip = paste0("<b>", infraccion, "</b><br>", vehiculo, ": ", fm(n), " comparendos"))  # etiqueta con saltos de línea y texto del hover
orden1 <- q1b %>% group_by(infraccion, et) %>% summarise(t = sum(n), .groups = "drop") %>% arrange(t) %>%  # total por infracción ordenado de menor a mayor
  mutate(tip = paste0("<b>", infraccion, "</b><br>Total: ", fm(t), " comparendos"))  # texto del hover con el total
p_barras <- plot_ly(height = 460)  # gráfico vacío para las barras
for (veh in names(col_veh)) {  # para cada vehículo...
  p_barras <- add_bars(p_barras, data = filter(q1b, vehiculo == veh), x = ~n, y = ~et, orientation = "h",  # agrega barras horizontales con su color
                       name = veh, marker = list(color = col_veh[[veh]]), hoverinfo = "text", hovertext = ~tip)  # (continúa: nombre y hover)
}  # fin del for
p_barras <- p_barras %>%  # continúa el gráfico con %>%
  add_trace(data = orden1, x = ~t, y = ~et, type = "scatter", mode = "text", text = ~fm(t),  # agrega capa de texto con el total
            textposition = "middle right", textfont = list(size = 14, color = pal$marino),  # (posición y estilo)
            showlegend = FALSE, hoverinfo = "text", hovertext = ~tip) %>%  # (sin leyenda; con hover)
  layout(barmode = "stack", xaxis = eje_val(max(orden1$t) * 1.15), yaxis = eje_cat(orden1$et)) %>%  # barras apiladas y ejes
  pl("Comparendos por infracción y vehículo")  # estilo y título

htmltools::div(class = "dos-col", style = "grid-template-columns:1fr 1.5fr", graf(p_dona), graf(p_barras))  # muestra la dona y las barras lado a lado (1 : 1,5)
# Tabla de la consulta 1
t1 <- datos %>% group_by(infraccion) %>%  # por infracción: autos, motos, total y valor
  summarise(Auto = sum(vehiculo == "Auto"), Moto = sum(vehiculo == "Moto"), Total = n(), Valor = sum(costo_de_comparendo), .groups = "drop") %>%  # (continúa)
  arrange(desc(Total)) %>%  # ordena por total descendente
  mutate(`% registros` = pct(Total / sum(Total)), Valor = cop(Valor), across(c(Auto, Moto, Total), fm)) %>%  # porcentaje de registros y formato del valor y los conteos
  rename(`Infracción` = infraccion)  # renombra la columna de infracción con tilde
salida(tabla_html(t1))  # imprime la tabla
Infracción Auto Moto Total Valor % registros
Velocidad superior a la máxima permitida 1.467 159 1.626 $ 418.695.000 76,7%
No detenerse ante una luz roja o amarilla 363 21 384 $ 197.760.000 18,1%
No respetar el paso de peatones 105 0 105 $ 27.037.500 5,0%
Transitar en sentido contrario 2 2 4 $ 206.000 0,2%

Consulta 2. Distribución de comparendos por propietario y tipo de vehículo

Cómo entender este gráfico

Qué muestra: los 15 propietarios con más comparendos y qué parte de ellos corresponde a autos y a motos.

Cómo leerlo: cada barra horizontal es un propietario; el número al final es su total de comparendos. Los colores dividen la barra entre autos (azul) y motos (coral).

Al pasar el cursor: sobre cada tramo de color aparecen el nombre completo del propietario y los comparendos de ese vehículo.

Para qué sirve: ubicar a los propietarios que más comparendos acumulan, casi siempre entidades financieras o empresas, para priorizar la gestión de cobro.

# Top 15 propietarios, barras apiladas por vehículo
top15 <- prop %>% slice_max(n, n = 15, with_ties = FALSE) %>% arrange(n) %>%  # los 15 propietarios con más comparendos, de menor a mayor
  mutate(et = wrapbr(ejecutado, 30), tip = paste0("<b>", ejecutado, "</b><br>Total: ", n, " comparendos"))  # (continúa: etiqueta y hover)
q2 <- datos %>% filter(ejecutado %in% top15$ejecutado) %>% count(ejecutado, vehiculo) %>%  # comparendos por propietario y vehículo
  mutate(et = wrapbr(ejecutado, 30), tip = paste0("<b>", ejecutado, "</b><br>", vehiculo, ": ", n, " comparendos"))  # (continúa: etiqueta y hover)
p <- plot_ly(height = 600)  # gráfico vacío de alto 600
for (veh in names(col_veh)) {  # para cada vehículo...
  p <- add_bars(p, data = filter(q2, vehiculo == veh), x = ~n, y = ~et, orientation = "h",  # agrega barras horizontales
                name = veh, marker = list(color = col_veh[[veh]]), hoverinfo = "text", hovertext = ~tip)  # (continúa)
}  # fin del for
p <- p %>%  # continúa el gráfico con %>%
  add_trace(data = top15, x = ~n, y = ~et, type = "scatter", mode = "text", text = ~n,  # agrega capa de texto con el total
            textposition = "middle right", textfont = list(size = 14, color = pal$marino),  # (posición y estilo)
            showlegend = FALSE, hoverinfo = "text", hovertext = ~tip) %>%  # (sin leyenda; con hover)
  layout(barmode = "stack", xaxis = eje_val(max(top15$n) * 1.12, tickformat = "d"), yaxis = eje_cat(top15$et)) %>%  # barras apiladas y ejes
  pl("Los 15 propietarios con más comparendos")  # estilo y título
graf(p)  # muestra el gráfico
Hallazgo

Los propietarios con más comparendos son entidades financieras y empresas (leasing y transporte). Hay 1.247 propietarios distintos y 899 (72%) tienen un solo comparendo. En el dashboard esta consulta estaba limitada a domingos y propietarios con 3 o más comparendos (67 registros).

Consulta 3. Distribución porcentual del valor económico por propietario

Cómo entender este gráfico

Qué muestra: qué porcentaje del dinero total de los comparendos corresponde a los 6 propietarios con mayor valor y qué parte queda en «Otros propietarios».

Cómo leerlo: cada porción de la dona es un propietario y su tamaño es su participación en el valor total; el porcentaje está dentro de la porción y en la leyenda de la derecha. El centro muestra el valor total.

Al pasar el cursor: sobre una porción aparecen el propietario, su valor en pesos y su porcentaje. Si haces clic en la leyenda, ocultas o muestras esa porción.

Para qué sirve: medir qué tan concentrado o repartido está el valor: si «Otros propietarios» es la porción más grande, el valor está muy Fragmentado.

# Dona del valor económico: top 6 propietarios y el resto
q3 <- datos %>% group_by(ejecutado) %>% summarise(v = sum(costo_de_comparendo), .groups = "drop") %>% arrange(desc(v)) %>%  # valor por propietario, de mayor a menor
  mutate(grupo = if_else(row_number() <= 6, ejecutado, "Otros propietarios")) %>%  # agrupa fuera del top 6 como 'Otros propietarios'
  group_by(grupo) %>% summarise(v = sum(v), .groups = "drop") %>%  # suma el valor por grupo
  mutate(p = v / sum(v), orden = if_else(grupo == "Otros propietarios", 0, v)) %>% arrange(desc(orden)) %>%  # porcentaje y orden (Otros primero)
  mutate(et = str_trunc(grupo, 32))  # recorta nombres largos a 32 caracteres
colores3 <- c(pal$azul, pal$turquesa, pal$ambar, pal$coral, pal$violeta, pal$marino, pal$gris)  # colores de las porciones
p <- plot_ly(q3, labels = ~et, values = ~v, type = "pie", hole = 0.58, sort = FALSE,  # dona del valor por propietario
             direction = "clockwise", textinfo = "percent", insidetextorientation = "horizontal",  # sentido horario y porcentaje dentro de la porción
             textfont = list(color = "white", size = 14),  # texto blanco
             marker = list(colors = colores3[seq_len(nrow(q3))], line = list(color = "white", width = 3)),  # colores y borde blanco
             hovertemplate = "<b>%{label}</b><br>$ %{value:,.0f}<br>%{percent:.1%}<extra></extra>",  # hover con valor en pesos
             height = 500) %>%  # alto del gráfico
  layout(annotations = list(list(text = paste0("Total<br><b>", cop(sum(q3$v)), "</b>"), x = 0.5, y = 0.5,  # texto central con el valor total
                                 showarrow = FALSE, font = list(size = 16, color = pal$marino)))) %>%  # (continúa: tamaño y color)
  pl("Valor económico por propietario", margen = list(t = 70, r = 10, b = 20, l = 10)) %>%  # estilo y título
  layout(legend = list(orientation = "v", x = 1.02, y = 0.5, font = list(size = 13)))  # leyenda vertical a la derecha
graf(p)  # muestra el gráfico
Observación

El valor económico está muy fragmentado: los 6 mayores propietarios suman solo el 10,5% del valor total.

Consulta 4. Top 10 de propietarios con más comparendos

Cómo entender esta tabla

Qué muestra: una tabla con los 10 propietarios que más comparendos acumulan, con su tipo de identificación, cantidad, valor y participación.

Cómo leerlo: cada fila es un propietario, ordenado del que más comparendos tiene al que menos. La columna «% del total» incluye una barrita cuyo largo es proporcional a su participación.

Al pasar el cursor: la fila bajo el cursor se resalta para seguirla con facilidad.

Para qué sirve: tener a la mano la lista concreta de propietarios a priorizar en la gestión de cobro.

# Top 10 de propietarios (conteo de comparendos, no suma de códigos)
q4 <- datos %>% group_by(ejecutado, tipo_id) %>% summarise(n = n(), v = sum(costo_de_comparendo), .groups = "drop") %>%  # comparendos y valor por propietario y tipo de ID
  arrange(desc(n)) %>% slice_head(n = 10) %>% mutate(p = n / nrow(datos))  # ordena y toma los 10 primeros, con su porcentaje
t4 <- q4 %>% transmute(`#` = row_number(), Propietario = ejecutado, `Tipo de ID` = tipo_id, Comparendos = n,  # tabla final: número, propietario, tipo de ID y comparendos
                       Valor = cop(v), SMLV = fm(v / smlv_2010),  # valor en pesos y en SMLV
                       `% del total` = paste0('<span class="mini" style="width:', as.integer(round(p / max(p) * 60)), 'px"></span>', pct(p)))  # porcentaje con barrita proporcional
salida(tabla_html(t4))  # imprime la tabla
# Propietario Tipo de ID Comparendos Valor SMLV % del total
1 LEASING BANCOLOMBIA S.A. C.F. NIT 61 $ 19.827.500 38 2,9%
2 TRANSPORTES MST Y CIA S EN C NIT 48 $ 13.905.000 27 2,3%
3 FINANCIERA INTERNACIONAL S.A. NIT 32 $ 10.557.500 20 1,5%
4 LEASING DE OCCIDENTE S.A. C.F. NIT 28 $ 9.527.500 18 1,3%
5 LILIANA ROZO PINZON Cédula de ciudadanía 27 $ 7.467.500 14 1,3%
6 GMAC FINANCIERA DE COLOMBI NIT 21 $ 6.180.000 12 1,0%
7 LEASING DE CREDITO S.A. NIT 21 $ 5.922.500 12 1,0%
8 UINON FAMILIAR CHARRIS S.EN C NIT 13 $ 4.120.000 8 0,6%
9 ELVIRA DEL CARMEN GARRIDO AREVALO Cédula de ciudadanía 10 $ 2.575.000 5 0,5%
10 MIGUEL HERNANDO GARAY CALLE Cédula de ciudadanía 9 $ 2.111.500 4 0,4%
Nota

El top 10 concentra el 12,7% de los comparendos y el 12,8% del valor.

Consulta 5. Frecuencia de infracciones por tipo de identificación y género

Cómo entender este gráfico

Qué muestra: a la izquierda, cuántos comparendos hay según el documento con que se identifica el infractor (cédula de ciudadanía, de extranjería o NIT); a la derecha, cada infracción dividida por género o tipo de titular.

Cómo leerlo: en las columnas, la altura y el número arriba indican la cantidad de comparendos. En las barras horizontales, la longitud es la cantidad de comparendos de cada infracción y los colores indican quién la cometió (mujer, hombre, empresa).

Al pasar el cursor: sobre una columna aparecen el tipo de documento y su cantidad; sobre un tramo de color, la infracción completa y los comparendos de ese género.

Para qué sirve: conocer el perfil de quien comete cada infracción para diseñar mensajes y controles distintos para personas y empresas.

# Barras por tipo de identificación + infracción por género
q5a <- datos %>% count(tipo_id) %>% arrange(desc(n)) %>%  # comparendos por tipo de identificación
  mutate(et = wrapbr(tipo_id, 14), tip = paste0("<b>", tipo_id, "</b><br>", fm(n), " comparendos"))  # etiqueta con saltos de línea y texto del hover
pa <- plot_ly(q5a, x = ~et, y = ~n, type = "bar",  # gráfico de columnas por tipo de ID
              marker = list(color = c(pal$azul, pal$turquesa, pal$ambar)[seq_len(nrow(q5a))]),  # colores de las columnas
              text = ~fm(n), textposition = "outside", cliponaxis = FALSE, textfont = list(size = 14, color = pal$marino),  # texto exterior
              hoverinfo = "text", hovertext = ~tip, height = 470) %>%  # hover y alto
  layout(xaxis = eje_cat(q5a$et), yaxis = eje_val(max(q5a$n) * 1.2)) %>%  # ejes
  pl("Por tipo de identificación", leyenda = FALSE, margen = list(t = 70, r = 10, b = 60, l = 20))  # estilo y título

q5b <- datos %>% count(infraccion, genero = str_to_title(genero)) %>%  # comparendos por infracción y género
  mutate(et = wrapbr(infraccion, 22), tip = paste0("<b>", infraccion, "</b><br>", genero, ": ", fm(n), " comparendos"))  # etiqueta y hover
orden5 <- q5b %>% group_by(et) %>% summarise(t = sum(n), .groups = "drop") %>% arrange(t)  # total por infracción para ordenar
pb <- plot_ly(height = 470)  # gráfico vacío para las barras
for (g in unique(q5b$genero)) {  # para cada género...
  pb <- add_bars(pb, data = filter(q5b, genero == g), x = ~n, y = ~et, orientation = "h", name = g,  # agrega barras horizontales por género
                 marker = list(color = unname(col_gen[g])), hoverinfo = "text", hovertext = ~tip)  # (continúa: color y hover)
}  # fin del for
pb <- pb %>% layout(barmode = "stack", xaxis = eje_val(max(orden5$t) * 1.05), yaxis = eje_cat(orden5$et)) %>%  # barras apiladas y ejes
  pl("Infracción según género")  # estilo y título

htmltools::div(class = "dos-col", style = "grid-template-columns:1fr 1.4fr", graf(pa), graf(pb))  # muestra ambos gráficos en dos columnas
Total a conciliar

La base depurada completa tiene 2.119 registros y 4 infracciones: «Transitar en sentido contrario» solo aparece en días que no son domingo.

Consulta 6. Evolución de los comparendos (semanal y mensual)

Cómo entender este gráfico

Qué muestra: cómo cambian semana a semana el número de comparendos (barras turquesa, eje izquierdo) y el dinero que suman (línea ámbar, eje derecho, en millones de pesos).

Cómo leerlo: cada barra es una semana que empieza el lunes indicado en el eje horizontal; su altura y el número encima son los comparendos. La línea ámbar sube o baja según el valor económico de esa semana. La última semana está incompleta.

Al pasar el cursor: sobre una barra o un punto de la línea aparecen la semana, los comparendos y el valor económico de esa semana.

Para qué sirve: ver si el valor sube igual que la cantidad de comparendos o si cambia por el tipo de infracción, y detectar semanas críticas.

# Barras de comparendos + línea de valor económico (doble eje), por semana
q6 <- datos %>% mutate(semana = lubridate::floor_date(fecha, "week", week_start = 1)) %>%  # agrupa por semana (inicia el lunes)
  group_by(semana) %>% summarise(n = n(), v = sum(costo_de_comparendo), .groups = "drop") %>%  # cuenta comparendos y suma valor por semana
  mutate(tip = paste0("<b>Semana del ", format(semana, "%d/%m/%Y"), "</b><br>Comparendos: ", fm(n), "<br>Valor: ", cop(v)))  # texto del hover
p <- plot_ly(height = 480) %>%  # gráfico vacío de alto 480
  add_bars(data = q6, x = ~semana, y = ~n, width = 5 * 86400000, name = "Comparendos",  # barras de comparendos por semana
           marker = list(color = pal$turquesa), text = ~fm(n), textposition = "outside", cliponaxis = FALSE,  # color, texto exterior
           textfont = list(size = 14, color = pal$marino), hoverinfo = "text", hovertext = ~tip) %>%  # tamaño y color; hover
  add_trace(data = q6, x = ~semana, y = ~v, yaxis = "y2", type = "scatter", mode = "lines+markers",  # línea del valor en el eje derecho (y2)
            name = "Valor económico", line = list(color = pal$ambar, width = 4),  # nombre y estilo de la línea
            marker = list(color = pal$ambar, size = 9), hoverinfo = "text", hovertext = ~tip) %>%  # marcadores y hover
  layout(xaxis = list(title = "", type = "date", tickformat = "%d/%m", tickvals = as.character(q6$semana),  # eje x: fechas de cada semana
                      gridcolor = "#E5EAF2", fixedrange = TRUE),  # (continúa: cuadrícula)
         yaxis = eje_val(max(q6$n) * 1.2, title = list(text = "Comparendos", font = list(color = pal$turquesa))),  # eje izquierdo: comparendos
         yaxis2 = list(overlaying = "y", side = "right", range = c(0, max(q6$v) * 1.2), showgrid = FALSE,  # eje derecho: valor en pesos, formato abreviado
                       zeroline = FALSE, fixedrange = TRUE, tickprefix = "$ ", tickformat = ".2s",  # (continúa: sin línea cero y prefijo '$')
                       title = list(text = "Valor económico", font = list(color = pal$ambar)))) %>%  # (continúa: título del eje)
  pl("Comparendos (barras) y valor (línea) por semana<br><sup>Semana que inicia el lunes indicado; la última está incompleta</sup>",  # estilo y título con subtítulo
     margen = list(t = 95, r = 90, b = 55, l = 70))  # (continúa: márgenes amplios)
graf(p)  # muestra el gráfico
# Resumen mensual
t6 <- datos %>% group_by(Mes = mes) %>%  # resumen mensual: comparendos, días y valor
  summarise(Comparendos = n(), Dias = n_distinct(fecha), Valor = sum(costo_de_comparendo), .groups = "drop") %>%  # (continúa)
  mutate(`Promedio diario` = format(round(Comparendos / Dias, 1), nsmall = 1, decimal.mark = ",", trim = TRUE), Comparendos = fm(Comparendos),  # promedio diario y formato
         `Días con registros` = Dias, Valor = cop(Valor)) %>% select(-Dias)  # (continúa: días con registros y valor)
salida(tabla_html(t6))  # imprime la tabla
Mes Comparendos Valor Promedio diario Días con registros
Abril 711 $ 216.506.000 37,4 19
Mayo 1.408 $ 427.192.500 52,1 27
Cobertura limitada

Solo se analizan abril (desde el 12/04/2010) y mayo (hasta el 27/05/2010), con 2.119 registros y $ 643.698.500. No permite evaluar tendencias anuales ni estacionalidad; por eso la evolución se presenta por semana.

5

Hallazgos y conclusiones

Hallazgos principales

Calidad: 25 columnas, 0 valores vacíos y 1 fila duplicada exacta (de 2.120 a 2.119 registros).
Comparendos repetidos: 17 números de comparendo aparecen dos veces con distinto No. de mandamiento; hay que validar si es doble mandamiento o error de digitación.
Perfil del infractor: la categoría con más comparendos es «Mujer» (45,7%) y el vehículo más frecuente es el auto (91,4%); las empresas aportan el 22,0%.
Infracción dominante: «Velocidad superior a la máxima permitida» representa el 76,7% de los comparendos y el 65,0% del valor; las dos infracciones principales suman el 95,8% del valor total.
Fin de semana: sábado y domingo reúnen el 36,2% de los comparendos.
Evolución: mayo supera a abril en 98% en total y en 39% por día, porque abril solo cubre desde el 12/04/2010.
Concentración y reincidencia: el top 10 de propietarios suma solo el 12,7% de los comparendos y 72% de los propietarios tiene un único comparendo; entre las personas naturales, el mayor reincidente acumula 27.
Dashboard: las consultas 1, 5 y 6 estaban filtradas a domingos (396 registros, $ 116.647.500) y las 2 y 3 a domingos con 3 o más comparendos; la 4 sumaba códigos. Todo se corrigió en este informe.
Alcance: el período es corto (12/04/2010 a 27/05/2010), así que las conclusiones no son tendencias de largo plazo.
Conclusión general

Los resultados subrayan la importancia de implementar políticas públicas basadas en datos: desde campañas educativas focalizadas hasta operativos estratégicos según el tipo de vehículo, el día y el tipo de infractor. La gestión efectiva de los comparendos no solo debe sancionar, sino también prevenir, orientar y transformar los hábitos de conducción para mejorar la seguridad vial colectiva.

6

Recomendaciones

Calidad de los datos

1
Validar los comparendos con número repetido y la fila duplicada con el área de cobro coactivo.
2
Quitar o fijar de forma explícita las segmentaciones del dashboard (día = domingo) para que los totales coincidan en todas las consultas.
3
Normalizar la escritura de los propietarios (p. ej. GMAC / G.M.A.C.) y no truncar los nombres en la base.
4
Corregir la consulta 4 (contar comparendos, no sumar códigos) y la 3 (usar valor económico).

Gestión y control

5
Priorizar la gestión de las entidades financieras y empresas del top 10, y reforzar el control en fines de semana y sobre las infracciones de mayor valor.
6
Diseñar intervenciones educativas y sancionatorias focalizadas en los reincidentes, con estrategias diferenciadas para personas naturales y jurídicas.

Política pública

7
Destinar parte de los recursos recaudados a seguridad vial y registrar fechas de pago para medir el recaudo efectivo.
8
Ampliar la cobertura a más meses y años para medir tendencias y estacionalidad.
7

Referencias

Fuente de datos

Secretaría de Tránsito de Barranquilla. Base de datos de comparendos, abril–mayo de 2010 (archivo BD_Comparendos_TAD_13.xlsx).

Herramientas

Procesamiento y visualización en R version 4.6.1 (2026-06-24 ucrt) con los paquetes tidyverse, plotly, scales y htmltools.

Datos que mueven una movilidad más segura