En este tutorial, nos proponemos:
Leer y manejar en R la base de datos de los cómputos distritales de la elección de diputados del 2024, proporcionada por el Instituto Nacional Electoral (INE).
Trabajar con la base de datos de los convenios de coalición acordados para esta elección.
Analizar y determinar la composición de la Cámara de Diputados considerando:
Por composición, entendemos el número de diputados que cada partido obtiene al finalizar el proceso electoral, un aspecto clave ya que las decisiones en la Cámara dependen de las mayorías alcanzadas.
Finalmente, realizaremos análisis básicos y generaremos resultados que serán de interés para investigadores, analistas y cualquier persona interesada en comprender cómo se determina la composición legislativa a partir de los datos electorales.
Este tutorial tiene un enfoque exclusivamente académico, diseñado para comprender el proceso mediante el cual se determina la composición de la Cámara de Diputados y para aprender a manejar las bases de datos del INE. Aunque hemos seguido la normativa legal y los datos disponibles con la mayor precisión posible, es importante señalar lo siguiente:
Este tutorial tiene como único propósito entender los principios que rigen el cálculo de la composición legislativa y fomentar el análisis crítico de las bases de datos electorales. Los resultados obtenidos no deben considerarse como representativos de los datos oficiales ni como una postura sobre los resultados de esta elección en particular.
México está dividido en 300 distritos electorales federales (artículo 53 de la (CPEUM 2023)), que son las áreas geográficas utilizadas para elegir a los diputados que integran la Cámara de Diputados. Cada distrito agrupa a un cierto número de ciudadanos y es la base para organizar y contar los votos durante las elecciones.
Cuando se realiza una elección, el Instituto Nacional Electoral (INE) utiliza los distritos electorales para llevar a cabo los cómputos distritales, un proceso oficial donde se suman y verifican los votos registrados en las casillas instaladas dentro de cada distrito. Durante este procedimiento, se revisan las actas de votación de cada casilla y, si hay errores o inconsistencias, se pueden realizar recuentos. Al finalizar, los cómputos distritales producen los resultados oficiales que determinan a los ganadores.
No obstante, estos resultados, aunque oficiales, no son inamovibles. El Tribunal Electoral del Poder Judicial de la Federación (TEPJF) tiene la facultad de anular casillas o realizar recuentos en casillas específicas si se detectan irregularidades graves que afecten la certeza de los resultados.
Para garantizar la transparencia, el INE publica una base de datos detallada a nivel de casilla, lo que significa que cada fila en la base corresponde a una casilla electoral específica. Esta base incluye información como el número total de votos por partido o candidato, los votos nulos, y la participación ciudadana registrada en cada casilla. Al analizar esta base de datos, se pueden identificar patrones de votación, evaluar la participación en distintas áreas y explorar cómo se desarrolló el proceso electoral en cada distrito del país.
Los cómputos distritales son fundamentales en el sistema electoral de México y su aplicación depende del tipo de elección.
En las elecciones federales (presidencial, diputados y senadores), se utilizan los 300 distritos federales para consolidar y verificar los votos de todas las casillas dentro de cada distrito. Por ejemplo, cada distrito elige a un diputado federal por el principio de mayoría relativa, y los resultados se determinan mediante los cómputos distritales.
En las elecciones locales (como para gobernadores, congresos locales o alcaldías), se utilizan los distritos locales, que son definidos por cada estado y no siempre coinciden con los distritos federales. En estos casos, los cómputos se realizan a nivel local, de acuerdo con la división territorial electoral correspondiente.
En este tutorial, nos enfocaremos en analizar los cómputos distritales para la elección federal de diputados de 2024, utilizando la base de datos publicada por el INE a nivel de casilla.
Para obtener la base de datos de los cómputos distritales, visita la página oficial del INE:
Maximiza la ventana y haz clic en la pestaña superior “Base
de Datos”. Luego, selecciona el botón
“Descargar” que aparece en la parte izquierda de la
página para guardar el archivo comprimido
20240608_2030_COMPUTOS.zip
en tu computadora.
Al descomprimir este archivo, encontrarás tres archivos comprimidos
adicionales. El que nos interesa para esta tarea es
20240608_2030_COMPUTOS_DIP_FED.zip
. Descomprímelo y
obtendrás el archivo con los datos de la votación para la elección
federal de diputados a nivel casilla: DIP_FED_2024.csv
.
Antes de empezar a analizar los datos, es recomendable revisar el
archivo LEEME.txt,
donde se describe en detalle el
contenido de los archivos, los nombres de las variables y sus posibles
valores.
El siguiente código carga la base de datos
DIP_FED_2024.csv
asumiendo que colocamos esta base de datos
en el folder BD
. Para ello, se utiliza la función
fread()
de data.table
, que es muy eficiente
para manejar archivos grandes.
# DIRECTORIO DE TRABAJO
my_dir <- "/Users/carloserwin/Library/CloudStorage/GoogleDrive-carloserwin@sigma.iimas.unam.mx/Mi unidad/IIMAS/PRESENTACIONES/MAS_ALLA_DE_LOS_VOTOS_2024/EXTRAS/"
# LIBRERÍAS NECESARIAS
library(data.table)
library(xtable)
BD0 <- data.frame(fread(paste0(my_dir, "BD/DIP_FED_2024.csv"), skip = 6, na.strings = "-"))
names(BD0)
## [1] "CLAVE_CASILLA" "CLAVE_ACTA"
## [3] "ID_ENTIDAD" "ENTIDAD"
## [5] "ID_DISTRITO_FEDERAL" "DISTRITO_FEDERAL"
## [7] "SECCION" "ID_CASILLA"
## [9] "TIPO_CASILLA" "EXT_CONTIGUA"
## [11] "CASILLA" "TIPO_ACTA"
## [13] "PAN" "PRI"
## [15] "PRD" "PVEM"
## [17] "PT" "MC"
## [19] "MORENA" "CANDIDATO.A.INDEPENDIENTE"
## [21] "PAN_PRI_PRD" "PAN_PRI"
## [23] "PAN_PRD" "PRI_PRD"
## [25] "PVEM_PT_MORENA" "PVEM_PT"
## [27] "PVEM_MORENA" "PT_MORENA"
## [29] "CANDIDATO.A.NO.REGISTRADO.A" "VOTOS.NULOS"
## [31] "TOTAL_VOTOS_CALCULADOS" "LISTA_NOMINAL"
## [33] "OBSERVACIONES" "MECANISMOS_TRASLADO"
## [35] "FECHA_HORA"
En este caso, se omiten las primeras 6 filas del archivo mediante el
argumento skip = 6
, ya que el INE suele incluir comentarios
al inicio de las bases de datos, y los datos relevantes comienzan a
partir de la fila 6. Además, se indica que los valores “-”
deben ser tratados como datos faltantes (NA
) con el
argumento na.strings = “-”
. Finalmente, el resultado se
convierte en un data.frame
para facilitar su manipulación y
se guarda en el objeto BD0
.
A continuación, realizamos varios ajustes en los datos para mejorar su manejo y garantizar consistencia.
names(BD0)[c(20, 29, 30, 31)] <- c("CI", "CNR", "NULOS", "TOTAL")
BD0$ID_ENTIDAD <- gsub('^=\\"|\\\"$', '', BD0$ID_ENTIDAD)
BD0$ID_DISTRITO_FEDERAL <- gsub('^=\\"|\\\"$', '', BD0$ID_DISTRITO_FEDERAL)
BD0$ID_DF <- paste0(BD0$ID_ENTIDAD, BD0$ID_DISTRITO_FEDERAL)
Los pasos incluyen:
Cambiar nombres originales por versiones más manejables: Modificamos los nombres de las variables originales para que sean más cortos, descriptivos y fáciles de trabajar en R.
Corregir detalles en los identificadores de estado y
distrito: Los identificadores de estado vienen en el formato
“="01"”
, mientras que los de distrito federal tienen el
formato “="001"”
. Esto probablemente se debe a que el INE
usa este formato para evitar que programas como Excel interpreten los
valores como números en lugar de caracteres. Eliminamos los caracteres
adicionales (=
y comillas dobles) para obtener valores
consistentes y tratarlos como cadenas de texto (e.g., “01” para el
estado y “001” para el distrito).
Crear un identificador único de distrito federal: Para identificar de manera única cada distrito federal electoral (de los 300), combinamos las variables de estado y distrito en una nueva columna, asegurando que cada registro sea inequívoco. Esto es necesario porque cada estado tiene su propio distrito federal 1, distrito federal 2, y así sucesivamente.
Con estos ajustes, los datos estarán listos para un análisis sin ambigüedades.
Finalmente, generamos una nueva base de datos que contiene únicamente las variables necesarias para el análisis. Además, calculamos los sub-totales de votos por distrito federal para cada variable, ignorando las celdas con valores faltantes al realizar las sumas.
BD <- data.table(BD0[, c(36, 13:32)])
BD_DIST <- data.frame(BD[, lapply(.SD, sum, na.rm = TRUE), by = ID_DF])
dim(BD_DIST)
## [1] 300 21
## ID_DF PAN PRI PRD PVEM PT MC MORENA CI PAN_PRI_PRD PAN_PRI
## 1 01001 74830 23971 6565 8769 7587 15288 71065 0 2397 1128
## 2 01002 72198 8873 4829 5787 3624 20862 63580 0 2802 1099
## 3 01003 120511 14465 3473 6466 3483 16793 62028 0 0 0
## 4 02001 48257 8753 1451 6802 3726 15030 77248 0 1756 530
## 5 02002 33786 7401 1434 8147 5581 14428 85145 0 1214 393
## 6 02003 23621 9988 2952 11088 10034 13802 84747 0 1117 339
## PAN_PRD PRI_PRD PVEM_PT_MORENA PVEM_PT PVEM_MORENA PT_MORENA CNR NULOS TOTAL
## 1 187 56 1853 245 588 482 137 7178 222326
## 2 231 31 3100 198 724 603 218 4533 193292
## 3 0 0 3026 224 727 529 230 9149 241104
## 4 42 19 0 0 0 0 153 7249 171016
## 5 37 21 0 0 0 0 149 8575 166311
## 6 44 32 0 0 0 0 353 10939 169056
## LISTA_NOMINAL
## 1 364676
## 2 347196
## 3 385495
## 4 331719
## 5 342529
## 6 334438
La clave para entender la composición de la Cámara de Diputados después de la elección federal de 2024 es analizar los convenios de coalición. Según el artículo 87 de la (LGPP 2023), los partidos políticos tienen la posibilidad de formar coaliciones para competir en un distrito determinado.
Un aspecto crucial es que, si una coalición gana la diputación en un distrito, el cargo no necesariamente queda en manos del partido que obtuvo más votos dentro de la coalición. Esto se define con antelación en los convenios de coalición, los cuales son negociados y registrados varios meses antes de la elección.
Los convenios de coalición para diputados se pueden descargar en el siguiente enlace:
https://portal.ine.mx/actores-politicos/convenios-de-coalicion/
Para la elección de diputados del 2024, las coaliciones fueron:
PRI
, PAN
, y PRD
. Los
detalles de este convenio se encuentran en las páginas 45 a 55 del
documento en PDF.PT
, PVEM
, y MORENA
.
Este convenio está descrito en las páginas 43 a 51 del PDF.Igual que antes, asumiendo que colocamos esta base de datos en el
folder BD
, en R se carga de la siguiente
manera:
# LEEMOS LAS COALICIONES, SIN EL NOMBRE DEL ESTADO
COAL_D <- as.data.frame(fread(paste0(my_dir, "BD/COAL_D.csv")))[,-2]
dim(COAL_D)
## [1] 300 9
## ID_ESTADO ID_DISTRITO PAN PRI PRD MORENA PT PVEM CI
## 1 1 1 0 1 0 0 0 1 0
## 2 1 2 1 0 0 1 0 0 0
## 3 1 3 0 0 0 1 0 0 0
## 4 2 1 1 0 0 0 0 0 0
## 5 2 2 1 0 0 0 0 0 0
## 6 2 3 0 0 1 0 0 0 0
Como ya hemos visto anteriormente, para identificar de forma única
los distritos federales electorales en las bases de datos, se utilizan
las dos variables: ID_ESTADO
y
ID_DISTRITO
.
Las siguientes tres variables, PAN
, PRI
, y
PRD
, indican si en un distrito específico se acordó la
coalición FCPM. Si alguna de estas variables tiene un
valor de 1, significa que, en caso de que la coalición gane la
diputación en ese distrito, el partido correspondiente será el que
obtenga el cargo. Si las tres variables tienen un valor de 0, entonces
no hubo coalición FCPM en ese distrito.
De manera similar, las variables MORENA
,
PT
, y PVEM
funcionan para la coalición
SHH. Un valor de 1 en alguna de estas variables indica
que, si la coalición SHH gana en el distrito, el partido señalado con el
1 será el que obtenga la diputación. Si todas estas variables tienen un
valor de 0, significa que no hubo coalición SHH en el
distrito.
Finalmente, la variable CI
señala si en un distrito hubo
candidatos independientes compitiendo por la diputación, asignando un
valor de 1 cuando esto ocurrió.
El siguiente bucle nos permite obtener dos datos clave: primero, el número de distritos donde se acordaron las coaliciones; y segundo, la distribución de los asientos en la Cámara que cada partido de la coalición obtendría si ganara en todos los distritos donde dichas coaliciones fueron pactadas.
# COALICIONES
n <- nrow(COAL_D)
SHH <- rep("SIN COALICION", n)
FCPM <- rep("SIN COALICION", n)
for (i in 1:n) {
tmp1 <- c("MORENA", "PT", "PVEM")[COAL_D[i,c("MORENA", "PT", "PVEM")] > 0]
tmp2 <- c("PAN", "PRI", "PRD")[COAL_D[i,c("PAN", "PRI", "PRD")] > 0]
if(length(tmp1)){
SHH[i] <- tmp1
}
if(length(tmp2) > 0){
FCPM[i] <- tmp2
}
}
La coalición SHH se acordó en 260 distritos, mientras que la coalición FCPM se estableció en 294 distritos. Los acuerdos por partido quedaron de la siguiente manera:
## SHH
## MORENA PT PVEM SIN COALICION
## 143 46 71 40
## FCPM
## PAN PRD PRI SIN COALICION
## 113 70 111 6
Por ejemplo, si la coalición SHH ganara en los 260
distritos donde se pactó, los asientos en la Cámara de Diputados se
distribuirían de la siguiente forma: MORENA
obtendría 143
diputaciones, el PT
46, y el PVEM
71.
Es importante recalcar que estos acuerdos se definen varios meses antes de la elección, y su implementación determina cómo se distribuyen los asientos en caso de que una coalición resulte ganadora.
Antes de continuar, es fundamental verificar que la base de datos
BD_DIST
y los convenios de coalición COAL_D
sigan el mismo orden. Esta verificación se puede realizar con el
siguiente código:
ID_DF <- paste0(formatC(COAL_D$ID_ESTADO, width = 2, flag = "0"),
formatC(COAL_D$ID_DISTRITO, width = 3, flag = "0"))
sum(ID_DF == BD_DIST$ID_DF)
## [1] 300
En este paso, se genera un identificador único utilizando la
información de los convenios de coalición y se compara con el
identificador correspondiente en la base de datos que contiene la suma
de votos a nivel distrito. La comparación verifica que la coincidencia
sea exacta, lo cual asegura que ambas bases de datos están perfectamente
alineadas: los convenios de coalición del renglón i
en la
base de datos COAL_D
corresponden efectivamente a los votos
registrados en el renglón i
de la base de datos
BD_DIST
.
Para transformar los votos obtenidos en las urnas en asientos en la Cámara de Diputados, es necesario revisar el marco legal correspondiente. En primer lugar, el artículo 52 de la CPEUM (2023) establece que la Cámara de Diputados en México está compuesta por 500 diputados distribuidos de la siguiente manera:
El primer paso en este principio es distribuir los votos de las combinaciones válidas para votar por la coalición, siguiendo lo establecido en el artículo 311, inciso C, de la (LEGIPE 2023). En este análisis, realizaremos el procedimiento a nivel distrito federal.
Por ejemplo, las formas válidas de votar por la coalición SHH eran:
\[ PT, PVEM, MORENA, PVEM\_PT, PT\_MORENA, PVEM\_MORENA,\ \ \mbox{y}\ \ PVEM\_PT\_MORENA \]
Por esta razón, en la base de datos aparecen las combinaciones
PVEM_PT
, PT_MORENA
, PVEM_MORENA
y
PVEM_PT_MORENA
.
Para calcular los votos en favor de un partido específico, es
necesario distribuir los votos de las combinaciones entre los partidos
involucrados. Por ejemplo, para el PT
, de acuerdo con el
artículo 311 mencionado:
\[
PT_0 = PT + \frac{1}{2} PVEM\_PT + \frac{1}{2} PT\_MORENA + \frac{1}{3}
PVEM\_PT\_MORENA,
\] Un procedimiento similar se aplica a los partidos
PVEM
y MORENA
obteniendo \(PVEM_0\) y \(MORENA_0\).
Cuando realizamos la repartición de votos de las combinaciones entre cada partido multiplicando por fracciones, inevitablemente obtenemos resultados con decimales. Además, aunque analíticamente los totales puedan coincidir de manera exacta, al usar una computadora podrían surgir problemas de redondeo. Por lo tanto, los totales calculados a partir de las combinaciones de votos:
\[ TOT = PT + PVEM + MORENA + PVEM\_PT + PT\_MORENA + PVEM\_PT\_MORENA, \]
y
\[ TOT_0 = PT_0 + PVEM_0 + MORENA_0, \]
podrían no coincidir exactamente. Para abordar estas discrepancias, la ley establece que, en caso de fracciones, los votos restantes deben asignarse al partido con mayor votación.
Intentando acatar lo que indica la ley, se siguen los siguientes pasos:
Redondeamos hacia abajo (al entero más cercano pero menor) los valores \(PT_0\), \(PVEM_0\), y \(MORENA_0\), obteniendo \(PT_f\), \(PVEM_f\), y \(MORENA_f\).
Calculamos el nuevo total como: \[ TOT_f = PT_f + PVEM_f + MORENA_f. \] Como claramente \(TOT_f < TOT\), el déficit se define como: \[ \epsilon = TOT - TOT_f, \] un entero positivo que representa los votos que faltan para que las sumas coincidan.
Determinamos el partido con mayor votación entre \(PT_f\), \(PVEM_f\), y \(MORENA_f\). Supongamos que \(MORENA_f\) es el mayor:
De este modo, garantizamos que:
Los valores ajustados \(MORENA_c\), \(PT_c\), y \(PVEM_c\) sean números enteros.
El total ajustado coincida exactamente con el total original: \[ MORENA_c + PT_c + PVEM_c = TOT. \]
Aunque este procedimiento añade cierta complejidad, asegura que siempre manejemos cantidades enteras y que los totales originales a nivel distrito sean consistentes con los totales ajustados tras repartir los votos de las combinaciones válidas.
Finalmente, los votos correspondientes a las combinaciones de la coalición se eliminan de la base de datos para evitar duplicidades y simplificar el análisis. Este mismo procedimiento se aplica de manera análoga para la coalición FCPM.
A continuación, este algoritmo se implementa en R utilizando funciones sencillas, diseñadas para aplicarse de manera directa y garantizar que los datos sean consistentes y fáciles de trabajar.
# REPARTE TRES (RESOLVIENDO DECIMALES COMO INDICA LA LEY)
reparte_votos_coal_tres_partidos <- function(x, y, z, xy, xz, yz, xyz){
# SUMA TOTAL: PARA RESOLVER EL PROBLEMA DE LOS DECIMALES
tot <- x + y + z + xy + xz + yz + xyz
#
tmp1 <- 0.5*xy
x <- x + tmp1
y <- y + tmp1
#
tmp2 <- 0.5*xz
x <- x + tmp2
z <- z + tmp2
#
tmp3 <- 0.5*yz
y <- y + tmp3
z <- z + tmp3
#
tmp4 <- 0.3333333*xyz
x <- x + tmp4
y <- y + tmp4
z <- z + tmp4
# PARA RESOLVER EL PROBLEMA DE LOS DECIMALES
# OBVIAMENTE SUMANDO
# x + y + z != tot, POR LOS DECIMALES
# REDONDEAMOS HACIA ABAJO
x1 <- floor(x)
y1 <- floor(y)
z1 <- floor(z)
# SUMA TOTAL SIN DECIMALES:
tot1 <- x1 + y1 + z1
# VOTOS FALTANTES PARA QUE LOS TOTALES COINCIDAN
eps <- tot - tot1
# SEGÚN LA LEY:
# EN CASO DE QUE EXISTA UNA FRACCIÓN EN LOS VOTOS RESULTANTES,
# ESTOS SE ASIGNAN AL PARTIDO CON MAYOR VOTACIÓN.
is_x_max <- (x1 > y1) & (x1 > z1)
is_y_max <- (y1 > x1) & (y1 > z1)
is_z_max <- !(is_x_max | is_y_max)
# ASIGNANDO REMANENTE AL PARTIDO CON MAYOR VOTACIÓN
x1 <- x1 + eps*is_x_max
y1 <- y1 + eps*is_y_max
z1 <- z1 + eps*is_z_max
#
data.frame(x = x1, y = y1, z = z1)
}
diputados_reparte_votos_base <- function(BD){
FCPM <- reparte_votos_coal_tres_partidos(BD$PAN, BD$PRI, BD$PRD,
BD$PAN_PRI, BD$PAN_PRD, BD$PRI_PRD,
BD$PAN_PRI_PRD)
names(FCPM) <- c("PAN", "PRI", "PRD")
SHH <- reparte_votos_coal_tres_partidos(BD$PVEM, BD$PT, BD$MORENA,
BD$PVEM_PT, BD$PVEM_MORENA, BD$PT_MORENA,
BD$PVEM_PT_MORENA)
names(SHH) <- c("PVEM", "PT", "MORENA")
# BASE DE DATOS POR DF CON LOS VOTOS DE CADA PARTIDO DESPUÉS DE REPARTIR VOTOS POR LAS COMBINACIONES VÁLIDAS
# CANDIDATOS INDEPENDIENTES, CNR Y VN
cbind(FCPM, SHH, MC = BD$MC, CI = BD$CI,
CNR = BD$CNR, VN = BD$NULOS,
TOTAL = BD$TOTAL, LISTA_NOMINAL = BD$LISTA_NOMINAL)[,c("PAN", "PRI", "PRD", "PVEM", "PT", "MC", "MORENA",
"CI", "CNR", "VN", "TOTAL", "LISTA_NOMINAL")]
}
D <- diputados_reparte_votos_base(BD_DIST)
head(D)
## PAN PRI PRD PVEM PT MC MORENA CI CNR VN TOTAL LISTA_NOMINAL
## 1 76288 25361 7485 9803 8568 15288 72218 0 137 7178 222326 364676
## 2 73799 10371 5893 7281 5057 20862 65278 0 218 4533 193292 347196
## 3 120511 14465 3473 7950 4868 16793 63665 0 230 9149 241104 385495
## 4 49130 9612 2066 6802 3726 15030 77248 0 153 7249 171016 331719
## 5 34407 8012 1867 8147 5581 14428 85145 0 149 8575 166311 342529
## 6 24186 10545 3362 11088 10034 13802 84747 0 353 10939 169056 334438
Hacemos una verificación rápida para asegurarnos de que las fracciones se resolvieron de manera exacta. Esto lo hacemos comparando la suma total de votos por distrito, incluyendo los votos repartidos, con el total de votos original en la base de datos.
## [1] 0
ambos totales coinciden exactamente.
Con la base de datos D
y los convenios de coalición, es
sencillo determinar los diputados que gana cada partido bajo el
principio de MR.
Si en el distrito federal 1 (de 300) hubo una coalición, como la de SHH, se suman los votos de los partidos que la conforman. Si esta suma supera a la de la otra coalición o a la de los partidos que compiten en solitario, el asiento lo obtiene el partido designado en los acuerdos de coalición.
En caso de que no haya coaliciones en el distrito 1, los partidos compiten de manera individual, y el asiento lo gana simplemente el partido con más votos.
Este procedimiento se repite para cada uno de los 299 distritos federales restantes, generando un vector de longitud 300 con los partidos que ganaron en cada distrito.
A partir de este vector, se genera una tabla de frecuencias que muestra el número total de diputados que cada partido obtiene por el principio de MR. Es importante señalar que también pueden existir candidatos independientes que ganen alguna diputación bajo este principio; en este caso, los votos del candidato independiente deben superar tanto a la suma de los votos de cualquier coalición como a los de los partidos en solitario.
A continuación, implementaremos el procedimiento descrito para determinar los diputados que cada partido obtiene por el principio de MR. El objetivo es realizar este cálculo de manera clara, estructurada y eficiente, asegurando que el proceso sea reproducible y los resultados, precisos.
Comenzamos separando los convenios de coalición en los 300 distritos
para las dos alianzas: FCPM y SHH.
Esto se realiza dividiendo las columnas correspondientes de la base de
datos COAL_D
:
A continuación, identificamos los distritos donde hubo convenios de coalición para cada una de estas alianzas:
Ahora trabajaremos con la votación, en este caso extraemos la votación por distrito federal para las fuerzas políticas que compitieron por asientos en la Cámara de Diputados por el principio de MR:
## [1] "PAN" "PRI" "PRD" "PVEM" "PT" "MC" "MORENA" "CI"
Finalmente, creamos una variable con los nombres de estas fuerzas políticas para facilitar el análisis posterior.
A continuación hacemos la repartición, aquí se muestra el código.
MR_VECTOR <- rep(NA, 300)
for (i in 1:300) {
if (hay_fcpm[i]) {
convenio_fcpm <- c("PAN", "PRI", "PRD")[COAL_D_FCPM[i, ] > 0]
D0[i, convenio_fcpm] <- sum(D0[i, c("PAN", "PRI", "PRD")])
}
if (hay_shh[i]) {
convenio_shh <- c("PVEM", "PT", "MORENA")[COAL_D_SHH[i, ] > 0]
D0[i, convenio_shh] <- sum(D0[i, c("PVEM", "PT", "MORENA")])
}
MR_VECTOR[i] <- fuerzas[which.max(D0[i, ])]
}
MR_VECTOR <- factor(MR_VECTOR, levels = fuerzas)
MR <- table(MR_VECTOR)
MR
## MR_VECTOR
## PAN PRI PRD PVEM PT MC MORENA CI
## 32 9 1 57 38 1 161 1
El procedimiento anterior sigue estos pasos:
Para cada distrito (de los 300), verificamos si hubo un convenio de coalición para FCPM o SHH:
En cada distrito, determinamos el partido con el mayor número de votos después de aplicar los convenios de coalición.
Los resultados se almacenan en un vector llamado
MR_VECTOR
, que contiene el partido ganador para cada uno de
los 300 distritos.
Finalmente, generamos una tabla de frecuencias que muestra el número total de diputados que cada partido obtiene bajo este principio.
¿Qué pasaría si en lugar de seguir los convenios de coalición, asignáramos el asiento al partido que obtuvo más votos dentro de la coalición? Este es un interesante ejercicio académico que nos permite explorar una alternativa al procedimiento original.
Para ello, seguimos este procedimiento:
Creamos una copia de la base de datos, D0_MAX
, para
preservar los datos originales.
Iteramos sobre los 300 distritos. Si existe un convenio de coalición:
PAN
, PRI
, y
PRD
) y le asignamos la suma de los votos de toda la
coalición.PVEM
, PT
, y
MORENA
.Después de asignar los votos en cada distrito, determinamos el partido con más votos en el distrito correspondiente.
Finalmente, generamos una tabla que muestra la composición de la Cámara bajo esta lógica.
El código para implementar este procedimiento es el siguiente:
D0_MAX <- D[,1:8]
MR_VECTOR_MAX <- rep(NA, 300)
for (i in 1:300) {
if(hay_fcpm[i]){
max_fcpm <- c("PAN", "PRI", "PRD")[which.max(D0_MAX[i, c("PAN", "PRI", "PRD")])]
D0_MAX[i, max_fcpm] <- sum(D0_MAX[i, c("PAN", "PRI", "PRD")])
}
if(hay_shh[i]){
max_shh <- c("PVEM", "PT", "MORENA")[which.max(D0_MAX[i, c("PVEM", "PT", "MORENA")])]
D0_MAX[i, max_shh] <- sum(D0_MAX[i, c("PVEM", "PT", "MORENA")])
}
MR_VECTOR_MAX[i] <- fuerzas[which.max(D0_MAX[i,])]
}
MR_VECTOR_MAX <- factor(MR_VECTOR_MAX, levels = fuerzas)
MR_MAX <- table(MR_VECTOR_MAX)
MR_MAX
## MR_VECTOR_MAX
## PAN PRI PRD PVEM PT MC MORENA CI
## 35 7 0 6 0 1 250 1
Para comparar ambos enfoques, creamos una tabla que muestra la distribución de diputados obtenida por cada partido bajo el procedimiento original y el alternativo (asignar el asiento al partido con más votos dentro de la coalición). A continuación, presentamos los resultados:
# Crear una matriz con los resultados de ambos enfoques
comparacion <- cbind(Original = MR, Alternativo = MR_MAX)
# Mostrar la tabla de comparación
comparacion <- cbind(Original = MR, Alternativo = MR_MAX)
tabla <- knitr::kable(comparacion,
caption = "Comparación de la composición de la Cámara de Diputados por MR vía cada enfoque")
kableExtra::kable_styling(tabla,
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
position = "center")
Original | Alternativo | |
---|---|---|
PAN | 32 | 35 |
PRI | 9 | 7 |
PRD | 1 | 0 |
PVEM | 57 | 6 |
PT | 38 | 0 |
MC | 1 | 1 |
MORENA | 161 | 250 |
CI | 1 | 1 |
La principal diferencia en número de asientos entre ambos enfoques
radica en la concentración de los escaños. Bajo el método basado en
convenios, partidos como PVEM
y PT
logran una
representación significativa con 57 y 38 diputaciones, respectivamente,
mientras que en el enfoque alternativo estos pierden completamente sus
escaños, y MORENA
pasa de 161 a 250. De manera similar, en
FCPM, PAN
aumenta ligeramente su
representación, mientras que PRI
y PRD
ven
reducidos o eliminados sus escaños. Esto evidencia que el enfoque
alternativo tiende a concentrar el poder en los partidos dominantes
dentro de cada coalición.
Es importante notar la diferencia entre los dos enfoques presentados. En el caso de los convenios, los partidos políticos deciden con meses de antelación cómo se distribuirán los escaños en caso de que una coalición gane. Obviamente estos acuerdo no necesariamente refleja las preferencias individuales de los votantes dentro de la coalición, sino que obedece a estrategias políticas entre los partidos.
Por otro lado, el enfoque alternativo, donde el escaño se asigna al partido con más votos dentro de la coalición, refleja de manera más directa la voluntad expresada por los ciudadanos en las urnas. Este enfoque toma en cuenta qué partido fue más favorecido por los votantes, sin considerar los acuerdos previos entre los partidos políticos.
El principio de reparto proporcional, parecería muy sencillo sin embargo es imprescindible revisar la ley para entender que esta percepción es equivocada.
Es esencial comprender las distintas votaciones que establece la ley (artículo 15 de la (LEGIPE 2023)):
Votación Total Emitida (VTE): Incluye todos los votos registrados en las casillas.
Votación Válida Emitida (VVE): Resulta de descontar de la VTE los votos anulados y los emitidos a favor de candidatos no registrados. Cabe mencionar que esta categoría sí considera los votos destinados a candidatos independientes.
Votación Nacional Emitida (VNE): Se calcula a partir de la VVE, excluyendo los votos a favor de candidatos independientes y de partidos que no alcanzaron al menos el 3% de la VVE.
Estos conceptos son fundamentales para la asignación de los 200 diputados por RP, donde la VNE es la base para la primera distribución. Sin embargo, como se observa, el punto de partida inicial siempre es la VTE, como se ilustra en la tabla siguiente:
VTE <- colSums(D)[-12]
VVE <- VTE
VVE[9:11] <- 0
VVE[11] <- sum(VVE)
TOT <- data.frame(VTE = VTE, VVE = VVE)
p_VVE <- TOT$VVE/TOT$VVE[11]
TOT$p_VVE <- 100*p_VVE
TOT$VNE <- 0
TOT$VNE[p_VVE >= 0.03] <- TOT$VVE[p_VVE >= 0.03]
TOT$VNE[11] <- 0
TOT$VNE[11] <- sum(TOT$VNE)
p_VNE <- TOT$VNE/TOT$VNE[11]
TOT$p_VNE <- 100*p_VNE
TOT$RP_0 <- 200*p_VNE
TOT
## VTE VVE p_VVE VNE p_VNE RP_0
## PAN 10049375 10049375 17.5604655 10049375 18.040180 36.08036
## PRI 6623712 6623712 11.5743980 6623712 11.890586 23.78117
## PRD 1449744 1449744 2.5333097 0 0.000000 0.00000
## PVEM 4993874 4993874 8.7263887 4993874 8.964775 17.92955
## PT 3254753 3254753 5.6874162 3254753 5.842784 11.68557
## MC 6497404 6497404 11.3536851 6497404 11.663844 23.32769
## MORENA 24286396 24286396 42.4385018 24286396 43.597831 87.19566
## CI 72012 72012 0.1258351 0 0.000000 0.00000
## CNR 49329 0 0.0000000 0 0.000000 0.00000
## VN 2189869 0 0.0000000 0 0.000000 0.00000
## TOTAL 59466468 57227270 100.0000000 55705514 100.000000 200.00000
A partir de la matriz D
construida previamente, se
obtiene la VTE sumando los votos en las columnas,
excluyendo la lista nominal que no es relevante aquí. La
VVE se calcula eliminando de la VTE
los votos nulos y los correspondientes a candidatos no registrados,
generando un nuevo total.
Posteriormente, se calculan los porcentajes de la VVE con respecto a su total, los cuales sirven para determinar la VNE. Esta última incluye únicamente a los partidos que superan el 3% de los votos válidos y excluye los votos de candidatos independientes.
Finalmente, se calcula el total de la VNE, sus porcentajes relativos, y en una primera iteración se reparten los 200 diputados por RP considerando estos porcentajes. Sin embargo, nuevamente enfrentamos un problema de redondeo. Para garantizar que los valores sean enteros y que la suma de los diputados sea exactamente 200, la ley establece el uso de la técnica del resto mayor. A continuación, se muestra una función en R que implementa una estrategia análoga.
redondea_bien <- function(nh0, n){
nh1 <- floor(nh0)
n1 <- sum(nh1)
eps <- nh0 - nh1
o <- order(eps, decreasing = TRUE)
d <- n - n1
nh <- nh1
nh[o][1:d] <- nh1[o][1:d] + 1
nh
}
TOT$RP_1 <- c(redondea_bien(TOT$RP_0[1:7], 200), c(0, 0, 0, 200))
TOT
## VTE VVE p_VVE VNE p_VNE RP_0 RP_1
## PAN 10049375 10049375 17.5604655 10049375 18.040180 36.08036 36
## PRI 6623712 6623712 11.5743980 6623712 11.890586 23.78117 24
## PRD 1449744 1449744 2.5333097 0 0.000000 0.00000 0
## PVEM 4993874 4993874 8.7263887 4993874 8.964775 17.92955 18
## PT 3254753 3254753 5.6874162 3254753 5.842784 11.68557 12
## MC 6497404 6497404 11.3536851 6497404 11.663844 23.32769 23
## MORENA 24286396 24286396 42.4385018 24286396 43.597831 87.19566 87
## CI 72012 72012 0.1258351 0 0.000000 0.00000 0
## CNR 49329 0 0.0000000 0 0.000000 0.00000 0
## VN 2189869 0 0.0000000 0 0.000000 0.00000 0
## TOTAL 59466468 57227270 100.0000000 55705514 100.000000 200.00000 200
La sobrerrepresentación en la Cámara de Diputados ocurre cuando la proporción de curules que ocupa un partido político excede significativamente su porcentaje de apoyo electoral a nivel nacional. Esto puede distorsionar la relación entre la voluntad de los votantes y la composición legislativa. Para limitar esta situación, el artículo 15 de la (LEGIPE 2023) establece dos restricciones:
En ningún caso, un partido político podrá contar con un número de diputados por ambos principios que representen un porcentaje del total de la Cámara que exceda en 8 puntos a su porcentaje de VNE. Esta base no se aplicará al partido político que, por sus triunfos en distritos uninominales, obtenga un porcentaje de curules del total de la Cámara, superior a la suma del porcentaje de su votación nacional emitida más el 8%.
Ningún partido puede tener más de 300 asientos en total, sumando los obtenidos por MR y RP.
En términos matemáticos, ambas restricciones pueden ser homologadas y condensadas en la siguiente cota:
\[ \text{COTA} = \min\left\{300, \left\lfloor 500 \left( \textbf{VNE} \% + 8\% \right) \right\rfloor \right\}, \]
la cual define el número máximo de diputados que un partido puede obtener bajo ambos principios, MR + RP.
COTA <- pmin(300, floor(500*(p_VNE + 0.08)))
COTA[8:11] <- 0
MR <- c(MR, 0, 0, 300)
P1 <- data.frame(RP_1 = TOT$RP_1, MR = MR,
REP_1 = TOT$RP_1 + MR, COTA = round(COTA),
row.names = row.names(TOT))
P1
## RP_1 MR REP_1 COTA
## PAN 36 32 68 130
## PRI 24 9 33 99
## PRD 0 1 1 40
## PVEM 18 57 75 84
## PT 12 38 50 69
## MC 23 1 24 98
## MORENA 87 161 248 257
## CI 0 1 1 0
## CNR 0 0 0 0
## VN 0 0 0 0
## TOTAL 200 300 500 0
Como se aprecia, en ningún caso el número de diputados obtenido por la primera repartición por RP más los que ya se tenían por MR supera la cota. Entonces, esta primera repartición sería definitiva.
Volviendo al ejercicio planteado en la sección 3.1.4, en donde en lugar de considerar los convenios de coalción la diputación por MR la obtiene el partido de la coalción con mayor número de votos, se tendría lo siguiente.
MR3 <- c(MR_MAX, 0, 0, 300)
P2 <- data.frame(RP1 = TOT$RP_1, MR = MR3,
REP_1 = TOT$RP_1 + MR3, COTA = round(COTA),
row.names = row.names(TOT))
P2
## RP1 MR REP_1 COTA
## PAN 36 35 71 130
## PRI 24 7 31 99
## PRD 0 0 0 40
## PVEM 18 6 24 84
## PT 12 0 12 69
## MC 23 1 24 98
## MORENA 87 250 337 257
## CI 0 1 1 0
## CNR 0 0 0 0
## VN 0 0 0 0
## TOTAL 200 300 500 0
En este escenario ficticio, MORENA
supera la COTA de
sobre-representación por 80 asientos. Por ello, se aplica lo establecido
en el artículo 18 de la (LEGIPE 2023):
El exceso se corrige ajustando la representación de MORENA al límite máximo permitido en RP, quedando con solo 7 asientos por este principio. Este partido quedaría excluido del proceso de asignación restante. Es importante destacar que, según el artículo 15-3, los ajustes solo afectan la RP, mientras que los asientos obtenidos por MR permanecen intactos.
Se redefine la Votación Nacional Efectiva (VNEF), excluyendo al partido que rebasó la COTA.
Los diputados restantes (193 = 200 - 7, ya que a
MORENA
se le asignan los 7 correspondientes a su máximo) se
distribuyen proporcionalmente utilizando la VNEF y
aplicando la técnica del resto mayor para resolver problemas de redondeo
y garantizar una distribución equitativa.
TOT2 <- data.frame(VNE = TOT$VNE, VNEF = TOT$VNE,
row.names = row.names(TOT))
TOT2$VNEF[7] <- 0
TOT2$VNEF[11] <- sum(TOT2$VNEF[-11])
p_VNEF <- TOT2$VNEF/TOT2$VNEF[11]
TOT2$p_VNEF <- 100*p_VNEF
RP_MORENA <- P2$RP1[7] - (P2$REP_1[7] - P2$COTA[7])
d <- 200 - RP_MORENA
TOT2$RP_2 <- c(redondea_bien(d*p_VNEF[1:7], d), c(0, 0, 0, 200))
TOT2$RP_2[7] <- RP_MORENA
TOT2$MR_MAX <- c(MR_MAX, 0, 0, 300)
TOT2$REP_2 <- TOT2$RP_2 + TOT2$MR_MAX
TOT2$COTA <- COTA
TOT2
## VNE VNEF p_VNEF RP_2 MR_MAX REP_2 COTA
## PAN 10049375 10049375 31.98490 62 35 97 130
## PRI 6623712 6623712 21.08179 41 7 48 99
## PRD 0 0 0.00000 0 0 0 40
## PVEM 4993874 4993874 15.89438 30 6 36 84
## PT 3254753 3254753 10.35915 20 0 20 69
## MC 6497404 6497404 20.67978 40 1 41 98
## MORENA 24286396 0 0.00000 7 250 257 257
## CI 0 0 0.00000 0 1 1 0
## CNR 0 0 0.00000 0 0 0 0
## VN 0 0 0.00000 0 0 0 0
## TOTAL 55705514 31419118 100.00000 200 300 500 0
Con este ajuste todos los partidos satisfacel la COTA
# Crear una matriz con los resultados de ambos enfoques
comparacion2 <- data.frame(Original = P1$REP_1,
Alternativo = TOT2$REP_2, COTA = TOT2$COTA,
row.names = row.names(TOT2))
tabla2 <- knitr::kable(comparacion2,
caption = "Comparación de la composición de la Cámara de Diputados por MR + RP vía cada enfoque")
kableExtra::kable_styling(tabla2,
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
position = "center")
Original | Alternativo | COTA | |
---|---|---|---|
PAN | 68 | 97 | 130 |
PRI | 33 | 48 | 99 |
PRD | 1 | 0 | 40 |
PVEM | 75 | 36 | 84 |
PT | 50 | 20 | 69 |
MC | 24 | 41 | 98 |
MORENA | 248 | 257 | 257 |
CI | 1 | 1 | 0 |
CNR | 0 | 0 | 0 |
VN | 0 | 0 | 0 |
TOTAL | 500 | 500 | 0 |
Para apreciar la diferencia entre ambos enfoques, calculamos el número de diputados obtenidos por cada coalición. Con el enfoque original, la coalición SHH obtuvo 373 asientos, mientras que con el enfoque alternativo alcanzaría solo 313. Por otro lado, la coalición FCPM obtuvo 102 asientos con el enfoque original, mientras que con el enfoque alternativo serían 145.
Estos resultados sugieren que los convenios de la coalición SHH fueron una estrategia partidista eficaz para maximizar el número de asientos obtenidos por los partidos que la conforman.