Resumen
Cuatro medidas de poder para cada bancada en la LXVI Legislatura: porcentaje nominal de escaños, índice de Shapley-Shubik, índice de Banzhaf y poder empírico derivado de datos reales de votación nominal. Las divergencias entre estas medidas revelan partidos formalmente pequeños pero estratégicamente críticos — o viceversa.
Visualización: Distribución de poder
Compara el poder nominal (escaños) vs. el poder de negociación (Shapley/Banzhaf) por partido.
Cuatro medidas de poder
Cada medida captura una dimensión distinta de la influencia legislativa:
| Índice | Base | Qué mide |
|---|---|---|
| Nominal | Conteo de escaños | Representación formal — porcentaje de escaños sobre el total |
| Shapley-Shubik | Distribución de escaños | Poder de negociación — contribución marginal promediada en todos los ordenamientos |
| Banzhaf | Distribución de escaños | Poder de negociación — frecuencia de ser miembro crítico en coaliciones |
| Empírico | Votos reales | Relevancia real — qué tan frecuente fue decisivo el voto de un partido |
La comparación clave es nominal vs. empírico. Un partido con 5% de escaños pero un poder empírico de 20% es un rey Midas: sus votos son desproporcionadamente decisivos. Esto ocurre cuando la coalición dominante necesita frecuentemente a un partido pequeño para cruzar el umbral de mayoría.
Poder Nominal (Conteo de Escaños)
La medida más simple: la participación de cada partido en los escaños de la cámara.
poder_nominal[partido] = escaños_partido / total_escaños
La asignación de escaños maneja la multi-membresía — legisladores que pertenecen a más de un partido a lo largo de su carrera — asignando cada legislador al partido donde emitió más votos. Los empates se resuelven con la start_date más reciente de membresía.
Para la Cámara de Diputados el total es de 500 escaños. Para el Senado de la República, 128. Estos totales se derivan dinámicamente desde la base de datos vía get_total_seats(), sin valores hardcodeados.
Índice de Shapley-Shubik
El índice de Shapley-Shubik mide el poder de negociación de cada partido promediando su contribución marginal en todos los posibles ordenamientos en que podría formarse una coalición.
Concepto
Un partido es un pivote en la posición k de una permutación si la coalición de los primeros k partidos alcanza la mayoría, pero al eliminar ese partido la coalición cae por debajo de la mayoría. El índice es:
SS_i = (permutaciones donde i es pivote) / N!
Algoritmo de Programación Dinámica
El enfoque naive enumera todas las N! permutaciones — inviable para 13 partidos. La implementación usa un algoritmo DP que corre en tiempo O(n²W):
# dp[s][w] = número de subconjuntos de tamaño s con peso total w
# usando todos los jugadores EXCEPTO player_i
dp = [[0] * (quota) for _ in range(n)]
dp[0][0] = 1
for p in players:
if p == player_i:
continue
w_j = weights[p]
for s in range(n - 2, -1, -1):
for w in range(max_w - w_j, -1, -1):
if dp[s][w]:
dp[s + 1][w + w_j] += dp[s][w]
# SS_i = Σ dp_i[s][w] * s! * (n-1-s)! / n!
# para w < quota y w + w_i >= quota
Con 13 partidos y quota ~251 (mayoría simple en una cámara de 500 escaños), esto requiere aproximadamente 330K operaciones por jugador — tractable y exacto (sin muestreo).
:::tip El enfoque DP fue validado contra el método de fuerza bruta O(n!) en 4 datasets con diff = 0.0 en todos los casos. :::
Índice de Banzhaf
El índice de Banzhaf cuenta qué tan frecuente es cada partido un jugador crítico en coaliciones ganadoras. Un jugador es crítico si la coalición gana con él, pero pierde sin él.
Algoritmo
for coalition in todos_subconjuntos(players):
if peso_coalicion >= quota: # coalición ganadora
for player in coalition:
if peso_coalicion - pesos[player] < quota:
player es crítico
banzhaf[partido] = conteo_crítico[partido] / total_conteo_crítico
El resultado está normalizado: el puntaje de cada partido es su proporción del total de ocurrencias críticas en todas las coaliciones.
Con 8 partidos en la LXVI Legislatura, esto significa 2⁸ = 256 coaliciones — trivial de enumerar exhaustivamente.
Shapley-Shubik vs. Banzhaf
Ambos miden poder de negociación a partir de escaños, pero difieren en su tratamiento de la formación de coaliciones:
| Aspecto | Shapley-Shubik | Banzhaf |
|---|---|---|
| Promediado | Sobre todos los ordenamientos (permutaciones) | Sobre todas las coaliciones (subconjuntos) |
| Simetría | Considera orden de incorporación | Ignora el orden |
| Valores | Siempre suman 1.0 | Normalizados para sumar 1.0 |
En la práctica, producen rankings similares pero pueden divergir para partidos de tamaño medio en legislaturas fragmentadas.
Poder Empírico
Los índices nominales asumen disciplina perfecta de partido — cada miembro vota con su bancada. El poder empírico mide lo que realmente ocurre en las votaciones nominales.
Partidos Críticos por Votación
Para cada evento de votación, el módulo identifica qué partidos fueron necesarios para alcanzar el umbral de mayoría:
# Si aprobada: coalición ganadora = partidos que votaron a_favor
for partido in coalición_ganadora:
restante = total_a_favor - favor_partido
if restante < umbral_mayoría:
partido es "crítico" para esta votación
Un partido es crítico cuando, sin sus votos, el bando ganador habría caído por debajo de la mayoría requerida.
Índice de Poder Empírico
poder_empírico[partido] = veces_crítico[partido] / total_eventos_votación
Esto produce un puntaje de 0.0–1.0 que refleja qué tan frecuente fue decisivo el voto de un partido en el resultado. Un partido que está siempre en la coalición ganadora pero nunca es crítico obtiene un puntaje cercano a 0.0 — sus votos son redundantes.
Mayoría Calificada
El sistema soporta tanto mayoría simple como calificada (2/3). Para votaciones de mayoría calificada:
mayoría_necesaria = ceil(2/3 * total_escaños) # 334 para Diputados, 86 para Senado
El tipo de requerimiento se lee del campo motion.requirement en la base de datos (mayoria_simple o mayoria_calificada), así que el análisis se adapta automáticamente a las reglas de cada votación.
Soporte Bicameral
Todo el pipeline de análisis de poder soporta ambas cámaras vía el parámetro --camara:
| Cámara | ID de Organización | Escaños | --camara |
|---|---|---|---|
| Diputados | O08 | 500 | diputados |
| Senado | O09 | 128 | senado |
Los conteos de escaños se derivan dinámicamente desde la base de datos vía get_total_seats(db_path, camara), que consulta los registros reales de membresía en lugar de depender de constantes hardcodeadas. La función get_seat_counts() normaliza los valores mixtos de vote.group (algunos eventos usan nombres de partido como "PT", otros usan IDs de organización como "O02") antes de tomar el conteo máximo de votantes por partido, evitando números inflados por agregación entre legislaturas.
Votaciones Cerradas y Swing Voters
Votaciones Cerradas
Una votación es cerrada cuando el margen entre el bando ganador y perdedor cae por debajo de un umbral configurable:
CLOSE_VOTES_THRESHOLD = 10 # configurable en config.py
votación_cerrada = |a_favor - en_contra| < umbral
Las votaciones cerradas son las más consequentes — son donde los legisladores individuales tienen influencia real. El umbral por defecto es 10 pero puede ajustarse en analysis/config.py.
Swing Voters
Dentro de las votaciones cerradas, el módulo identifica swing voters: legisladores individuales que:
- Votaron diferente a la posición mayoritaria de su partido, Y
- Podrían haber cambiado el resultado con su voto individual
# Un legislador es swing voter si:
# - Su partido votó 'favor', pero él votó en contra
# - Y (a_favor_total - 1) < mayoría → un voto menos cambiaría el resultado
Solo se consideran legisladores en partidos con una posición mayoritaria clara (>50% de asistentes votando en una dirección). Partidos divididos o ausentes se excluyen.
Caso de Estudio: Reforma Judicial
Las votaciones de la reforma judicial (VE04 y VE05) se analizan como un caso especial porque requieren mayoría calificada (2/3):
REFORMA_JUDICIAL_VE_IDS = ["VE04", "VE05"]
mayoría_necesaria = ceil(2/3 * 500) = 334
Por Qué Importa
Bajo mayoría simple (251 escaños), un partido dominante puede aprobar legislación unilateralmente. Bajo mayoría calificada (334 escaños), incluso el partido más grande necesita socios de coalición. Esto cambia completamente el cálculo de poder:
- Partidos pequeños que tienen cero poder Shapley-Shubik bajo mayoría simple se vuelven críticos bajo 2/3
- La brecha entre poder nominal y empírico se amplía dramáticamente
- La estrategia de coalición se vuelve esencial
Desglose por Partido
Para cada votación de la reforma judicial, el análisis produce:
| Campo | Descripción |
|---|---|
| Posición del partido | favor, contra, split o ausente |
| Estatus crítico | Si al eliminar los votos de este partido la coalición cae por debajo de 334 |
| Margen | a_favor_total - mayoría_necesaria |
El desglose revela exactamente qué partidos fueron decisivos para la reforma — partidos cuya deserción habría hundido la votación.
Análisis de Disidentes
No todos los legisladores votan con su partido. El análisis de disidentes identifica los 10 legisladores que con mayor frecuencia rompen con la línea de su bancada.
Metodología
TOP_DISSENTERS_GLOBAL = 10 # configurable en config.py
for cada legislador:
for cada evento_votación:
if voto del legislador ≠ posición mayoritaria del partido:
conteo_disidencia += 1
tasa_disidencia = conteo_disidencia / total_votos
# Mínimo 10 votos requeridos para inclusión
Resultados
El análisis clasifica legisladores por tasa de disidencia (descendente), luego por conteo bruto de disidencias como desempate:
| Rank | Nombre | Partido | Tasa Disidencia | Total Votos | Votos Disidentes |
|---|---|---|---|---|---|
| 1 | … | … | …% | … | … |
Una tasa de disidencia alta puede indicar independencia ideológica, posicionamiento estratégico o votación impulsada por el constituency que diverge de la línea partidista. El cruce con los puntos ideales W-NOMINATE revela si los disidentes se agrupan ideológicamente o votan de forma idiosincrásica.