Cómo repartimos el voto por provincias

Del voto nacional a los escaños de cada provincia, explicado paso a paso con VOX en Granada. Página de referencia para los posts de las generales de 2026.
Autor/a

José Luis Cañadas Reche

Fecha de publicación

4 de noviembre de 2026

Fecha de última modificación

4 de noviembre de 2026

Ver código
library(tidyverse)

# números con coma decimal en el texto y en las tablas
num_es <- function(x, d = 2) {
  format(round(x, d), nsmall = d, decimal.mark = ",", big.mark = ".", trim = TRUE)
}
tabla <- function(d, digitos = 2) {
  knitr::kable(d, digits = digitos, format.args = list(decimal.mark = ","))
}

# referencia provincial y simulación del seguimiento
ref <- read_csv(
  here::here("2026/10/ref_provincial_23J_14.csv"),
  show_col_types = FALSE
)
sim <- readRDS(here::here("2026/10/full-bayesian/vivo/conjunto_sim.rds"))

# la misma corrección que simular_escanos.R: VOX en Santa Cruz de Tenerife
es_vox_tf <- ref$codigo_provincia == "38" & ref$partido == "VOX"
es_tf <- ref$codigo_provincia == "38" & ref$partido != "SALF"
ratio_tf <- 0.765
pct_tf <- ratio_tf * ref$pct_nac[es_vox_tf]
ref$ratio[es_vox_tf] <- ratio_tf
ref$pct_prov[es_vox_tf] <- pct_tf
ref$votos[es_vox_tf] <- round(sum(ref$votos[es_tf]) * pct_tf / (100 - pct_tf))

La idea es esta: si VOX vota en Granada un 30 % más que en España, supongo que seguirá pasando algo parecido, pero con un margen de error. Repito el cálculo 6.000 veces, cambiando un poco ese margen, y obtengo muchos repartos posibles.

Esta página lo explica con un ejemplo real, VOX en Granada, usando la simulación del 3 de noviembre de 2026. Las fórmulas y la validación están al final, en Para quien quiera más detalle.

Paso La pregunta Qué hago
1 ¿Cuánto vota esta provincia al partido comparada con España? Calculo el ratio
2 ¿Cuánto daría hoy si nada cambiara? Multiplico el voto nacional por el ratio
3 ¿Y si la geografía del voto ha cambiado? Cambio el ratio al azar: el shock
4 ¿Siguen cuadrando las cuentas? Recentro y renormalizo
5 ¿Quién se presenta realmente allí? Aplico las candidaturas de la provincia
6 ¿Cuántos escaños salen? Aplico el umbral del 3 % y D’Hondt
7 ¿Y por qué 6.000 veces? Repito todo para medir la incertidumbre

Paso 1. ¿Cuánto vota esta provincia al partido comparada con España?

Ver código
vox_granada_ref <- ref |> filter(provincia == "Granada", partido == "VOX")

El 23J, VOX sacó en Granada un 16,3 % y en España un 12,5 %. Si divido una cifra entre la otra:

16,3 / 12,5 = 1,30

A esta cifra la llamo ratio. Un ratio mayor que 1 significa que el partido va mejor allí que en el conjunto de España. Un ratio menor que 1 significa lo contrario.

Ver código
ref |>
  filter(
    provincia %in% c("Granada", "Madrid", "Barcelona"),
    partido %in% c("PP", "PSOE", "VOX")
  ) |>
  select(Provincia = provincia, partido, ratio) |>
  pivot_wider(names_from = partido, values_from = ratio) |>
  tabla()
Tabla 1: Ratio de cada partido en tres provincias (voto en la provincia / voto en España). 23J.
Provincia PP PSOE VOX
Barcelona 0,42 1,13 0,61
Granada 1,12 1,04 1,30
Madrid 1,23 0,88 1,13

Casi todos los ratios salen del 23J, con tres excepciones:

  • SALF: no existía en 2023, así que uso las Europeas de 2024.
  • Sumar y Podemos: en 2023 iban juntos. Los separo con su peso en las Europeas de 2024.
  • VOX en Santa Cruz de Tenerife: no tuvo lista el 23J, así que uso su ratio del 10N (más detalle).

Un partido que no se presenta en una provincia tiene ratio 0, y sigue en 0. Por eso ERC no recibe votos en Granada.

Paso 2. ¿Cuánto daría hoy si nada cambiara?

Ver código
voto_nacional <- colMeans(sim$shares)
voto_vox <- unname(voto_nacional["VOX"])
ratio_vox <- vox_granada_ref$ratio

El modelo de encuestas da a VOX un 19,45 % en España. Multiplico:

19,45 × 1,30 = 25,3 %

Paso 3. ¿Y si la geografía del voto ha cambiado?

Un partido no conserva exactamente su patrón entre elecciones. Por eso aplico al ratio un cambio al azar con dos partes:

  • Una común a la comunidad: afecta a todas las provincias de Andalucía. Sirve para casos como el PSC, que en 2023 subió en toda Cataluña.
  • Otra propia de la provincia: afecta solo a Granada.

A este cambio lo llamo shock.

Ver código
tau_brms <- read_csv(
  here::here("2026/10/tau_shock_brms.csv"),
  show_col_types = FALSE
)
tau_vox <- tau_brms |> filter(familia == "VOX")

# ratios de VOX y peso de cada provincia en votos
pesos <- ref |>
  group_by(provincia) |>
  summarise(votos = sum(votos)) |>
  mutate(peso = votos / sum(votos))

vox <- ref |>
  filter(partido == "VOX") |>
  select(provincia, ccaa, ratio) |>
  left_join(select(pesos, provincia, peso), by = "provincia")

set.seed(2029)

# un sorteo por comunidad
sorteo_comunidad <- tibble(ccaa = unique(vox$ccaa)) |>
  mutate(eta = rnorm(n(), mean = 0, sd = tau_vox$tau_c_med))

# un sorteo por provincia
vox <- vox |>
  left_join(sorteo_comunidad, by = "ccaa") |>
  mutate(
    eps = rnorm(n(), mean = 0, sd = tau_vox$tau_p_med),
    multiplicador = exp(eta + eps),
    ratio_con_shock = ratio * multiplicador
  )

vox_granada <- vox |> filter(provincia == "Granada")
tau_total_vox <- sqrt(tau_vox$tau_c_med^2 + tau_vox$tau_p_med^2)

En este sorteo, los dos cambios juntos multiplican el ratio de Granada por 0,89. Así, el ratio pasa de 1,30 a 1,16.

¿Cómo de grande es el cambio? No lo elijo yo: sale de cuánto se movieron los ratios en elecciones pasadas. Para VOX, un cambio típico multiplica o divide el ratio por 1,26, antes de los ajustes del paso siguiente. Los valores tau indican precisamente eso: si los cambios de un partido suelen ser grandes o pequeños.

Paso 4. ¿Siguen cuadrando las cuentas?

Después de los cambios al azar, hacen falta dos ajustes.

España debe seguir igual: el recentrado

Ver código
media_vox <- sum(vox$peso * vox$ratio_con_shock)
vox <- vox |> mutate(ratio_recentrado = ratio_con_shock / media_vox)
vox_granada <- vox |> filter(provincia == "Granada")

El voto nacional lo decide el modelo, no estos cambios al azar. En este sorteo, la media de los ratios de VOX en las 52 provincias, ponderada por sus votos, vale 1,040. Debería valer 1. Por eso divido todos sus ratios entre 1,040, y el de Granada queda en 1,12.

La provincia A tiene el 60 % de los votos y la B, el 40 %. Las dos parten de un ratio de 1. El shock lleva A a 1,10 y B a 0,95.

La media ponderada es 0,6 × 1,10 + 0,4 × 0,95 = 1,04. Sin más, el partido ganaría un 4 % de voto nacional. Si divido entre 1,04, A queda en 1,058 y B en 0,913, y la media vuelve a 1. El partido solo ha movido voto de B a A.

La provincia debe sumar 100 %: la renormalización

Ver código
granada <- ref |>
  filter(provincia == "Granada", ratio > 0) |>
  select(partido, ratio) |>
  mutate(
    voto_nacional = voto_nacional[partido],
    ratio_usado = if_else(partido == "VOX", vox_granada$ratio_recentrado, ratio),
    voto_antes = voto_nacional * ratio_usado,
    voto_final = 100 * voto_antes / sum(voto_antes)
  ) |>
  arrange(desc(voto_final))

suma_antes <- sum(granada$voto_antes)

granada |>
  select(
    Partido = partido,
    `Voto en España` = voto_nacional,
    `Ratio usado` = ratio_usado,
    `Voto antes de ajustar` = voto_antes,
    `Voto final` = voto_final
  ) |>
  tabla()
Tabla 2: Voto en Granada en este sorteo, con shock solo en VOX para que se siga mejor. Voto en %.
Partido Voto en España Ratio usado Voto antes de ajustar Voto final
PP 30,71 1,12 34,36 34,85
PSOE 27,18 1,04 28,30 28,71
VOX 19,45 1,12 21,79 22,10
SUMAR 6,91 1,00 6,90 7,00
RESTO 4,30 0,59 2,54 2,57
SALF 1,91 1,30 2,49 2,52
PODEMOS 2,55 0,87 2,22 2,25

Al multiplicar partido por partido, Granada suma 98,6 %, no 100 %. Por eso reajusto todos los partidos de la provincia en la misma proporción. En este sorteo, VOX queda en 22,1 %.

Paso 5. ¿Quién se presenta realmente allí?

Las coaliciones cambian de una provincia a otra, y por eso cada una aplica una regla:

Regla Dónde Qué hago con el voto
separadas 33 provincias Nada: Sumar y Podemos compiten por separado
unida C. Valenciana, Baleares y Canarias Sumo Podemos a Sumar, en una sola lista
sin_podemos Cataluña Reparto el voto de Podemos entre ERC, Sumar y fuera
sin_fa Teruel Reparto el voto de la familia Sumar entre PSOE y fuera
con_aa Andalucía Añado Adelante Andalucía y quito ese voto a otros

“Fuera” significa abstención u otras candidaturas. Los pesos de cada reparto se sortean en cada repetición.

Granada es una provincia con_aa. Adelante Andalucía no sale de las encuestas: su voto parte de su resultado en las autonómicas de mayo de 2026, con su patrón provincial. Primero quito ese voto a RESTO, el grupo de partidos pequeños. Si no llega, lo quito a Podemos, Sumar y PSOE, en proporción 4:4:1.

Ver código
voto_antes_regla <- setNames(granada$voto_final, granada$partido)

voto_aa <- unname(9.62 * sim$g_aa["Granada"])

de_resto <- min(voto_antes_regla["RESTO"], voto_aa)
falta <- voto_aa - de_resto

pesos_aa <- c(PODEMOS = 4, SUMAR = 4, PSOE = 1) / 9
quita <- pmin(falta * pesos_aa, voto_antes_regla[names(pesos_aa)])

voto_despues <- voto_antes_regla
voto_despues["RESTO"] <- voto_despues["RESTO"] - de_resto
voto_despues[names(pesos_aa)] <- voto_despues[names(pesos_aa)] - quita
voto_despues["AA"] <- voto_aa

tibble(
  `Sale de` = c("RESTO", "Podemos", "Sumar", "PSOE", "Total"),
  Puntos = c(de_resto, quita["PODEMOS"], quita["SUMAR"], quita["PSOE"], voto_aa)
) |>
  tabla()
Tabla 3: De dónde sale el voto de Adelante Andalucía en Granada en este sorteo. En puntos porcentuales.
Sale de Puntos
RESTO 2,57
Podemos 1,89
Sumar 1,89
PSOE 0,47
Total 6,83

Paso 6. ¿Cuántos escaños salen?

Quedan tres operaciones:

  1. Pongo a 0 los partidos con menos del 3 %.
  2. Pongo a 0 RESTO, porque no es una candidatura real.
  3. Reparto los 7 escaños con D’Hondt: cada escaño va al partido con mayor cociente voto / (escaños que ya tiene + 1).
Ver código
voto_dhondt <- voto_despues
voto_dhondt[voto_dhondt < 3] <- 0
voto_dhondt["RESTO"] <- 0
voto_dhondt <- voto_dhondt[voto_dhondt > 0]

escanos <- setNames(rep(0, length(voto_dhondt)), names(voto_dhondt))
for (ronda in 1:7) {
  cocientes <- voto_dhondt / (escanos + 1)
  ganador <- names(which.max(cocientes))
  escanos[ganador] <- escanos[ganador] + 1
}

tibble(
  Partido = names(voto_dhondt),
  `Voto (%)` = unname(voto_dhondt),
  `Escaños` = unname(escanos)
) |>
  arrange(desc(`Voto (%)`)) |>
  tabla(1)
Tabla 4: Voto y escaños en Granada en este sorteo.
Partido Voto (%) Escaños
PP 34,9 3
PSOE 28,2 2
VOX 22,1 2
AA 6,8 0
SUMAR 5,1 0

Paso 7. ¿Y por qué 6.000 veces?

Porque ese resultado es solo un sorteo. Cada repetición usa otro voto nacional y otros cambios al azar, en las 52 provincias y para todos los partidos. Al sumar, obtengo 6.000 parlamentos posibles. Esta es la distribución de los 7 escaños de Granada:

Ver código
esc_granada <- sim$prov_escanos[, "Granada", c("PP", "PSOE", "VOX", "SUMAR", "AA")]

as_tibble(esc_granada) |>
  pivot_longer(everything(), names_to = "Partido", values_to = "escanos") |>
  mutate(escanos = if_else(escanos >= 4, "4 o más", as.character(escanos))) |>
  count(Partido, escanos) |>
  group_by(Partido) |>
  mutate(porcentaje = 100 * n / sum(n)) |>
  ungroup() |>
  select(-n) |>
  pivot_wider(names_from = escanos, values_from = porcentaje, values_fill = 0) |>
  select(Partido, `0`, `1`, `2`, `3`, `4 o más`) |>
  arrange(desc(`4 o más`), desc(`3`)) |>
  tabla(1)
pp_vox <- sim$draws$PP + sim$draws$VOX
Tabla 5: Escaños en Granada: porcentaje de repeticiones con cada número de escaños. Simulación del 3 de noviembre de 2026, 6.000 repeticiones.
Partido 0 1 2 3 4 o más
PP 0,0 0,5 28,1 58,7 12,7
VOX 0,2 24,6 60,1 14,3 0,9
PSOE 0,0 7,7 66,4 25,2 0,8
AA 95,4 4,6 0,0 0,0 0,0
SUMAR 98,8 1,2 0,0 0,0 0,0

De aquí salen frases como “PP y VOX suman mayoría absoluta en el 94,6 % de las simulaciones”. Significa que suman al menos 176 escaños en ese porcentaje de las 6.000 repeticiones.

Lo que importa

Término Qué significa
Ratio El patrón del partido en cada provincia, comparado con España
Shock Cuánto puede cambiar ese patrón en cada repetición
Tau El tamaño típico de ese cambio, medido en elecciones pasadas
Recentrado Ajuste para que el shock no cree voto nacional
Renormalización Ajuste para que cada provincia sume 100 %
RESTO Partidos pequeños agrupados, que no reciben escaños
Draw Cada una de las 6.000 repeticiones
Dirichlet El método antiguo para cambiar el patrón, hoy jubilado

Para quien quiera más detalle

Esta parte es más técnica. No hace falta para entender el reparto.

Todo lo anterior lo hace simular(listas = "mapa"), en simular_escanos.R. Lo usan los posts De voto a escaños, Frente Amplio y Adelante Andalucía, el modelo full bayesian y su seguimiento.

El MRP multiencuesta no usa este reparto, porque estima directamente el voto de cada provincia. Sí comparte las reglas del paso 5, salvo en Teruel: simular() usa Dirichlet(PSOE 5,5; fuera 4,5) y el MRP, Dirichlet(PSOE 9; fuera 1).

Las fórmulas

Para la repetición \(s\), el partido \(f\) y la provincia \(p\), de la comunidad \(c(p)\):

\[ \log \tilde r^{(s)}_{f,p} = \log r_{f,p} + \eta^{(s)}_{f,c(p)} + \varepsilon^{(s)}_{f,p}, \qquad \eta^{(s)}_{f,c} \sim \mathcal{N}\left(0, \tau^{(s)}_{c,f}\right), \quad \varepsilon^{(s)}_{f,p} \sim \mathcal{N}\left(0, \tau^{(s)}_{p,f}\right) \]

El recentrado usa \(w_p\), el peso de la provincia en votos de la referencia:

\[ k^{(s)}_f = \frac{1}{\sum_{p} w_p \, \tilde r^{(s)}_{f,p}} \]

El voto provincial, con \(S^{(s)}_f\) como voto nacional del partido, es:

\[ v^{(s)}_{f,p} = \frac{S^{(s)}_f \, k^{(s)}_f \, \tilde r^{(s)}_{f,p}} {\sum_{g} S^{(s)}_g \, k^{(s)}_g \, \tilde r^{(s)}_{g,p}} \]

Por qué en logaritmo. Un cambio proporcional se convierte en una suma. Multiplicar por 1,10 suma 0,095 y dividir por 1,10 resta 0,095. Además, exp() nunca da un ratio negativo.

Los shocks se sortean por separado para cada partido, también para Sumar y Podemos.

De dónde salen los tau

Los tau salen de cuánto cambió el ratio entre generales consecutivas:

\[ \Delta \log r_{f,t,p} = \log \frac{r_{f,p}\ \text{en la elección nueva}}{r_{f,p}\ \text{en la anterior}} \]

Uso cuatro transiciones: 20D→26J, 26J→28A, 28A→10N y 10N→23J. VOX solo entra en las dos últimas. Separo las repeticiones (20D→26J y 28A→10N), porque en ellas el ratio cambia poco y yo quiero predecir una elección nueva, más de tres años después de la anterior.

El modelo de los cuatro partidos grandes se ajusta con brms en backtest_prov_loto.R:

bf(
  dlr ~ 0 + familia + repeticion + (0 + familia || codigo_ccaa),
  sigma ~ 0 + celda_sigma    # celda = partido × {fresca, repetición}
)

tau_c es la desviación típica del efecto de comunidad. tau_p es la desviación típica residual en las transiciones que no son repeticiones.

Ver código
tau_brms |>
  transmute(
    Partido = familia,
    tau_c = str_c(
      num_es(tau_c_med, 3), " [", num_es(tau_c_ic05, 3), "; ", num_es(tau_c_ic95, 3), "]"
    ),
    tau_p = str_c(
      num_es(tau_p_med, 3), " [", num_es(tau_p_ic05, 3), "; ", num_es(tau_p_ic95, 3), "]"
    )
  ) |>
  tabla()
Tabla 6: Tau de los cuatro partidos grandes: mediana e IC90 del posterior, en escala log-ratio.
Partido tau_c tau_p
PP 0,040 [0,026; 0,060] 0,171 [0,153; 0,193]
PSOE 0,023 [0,010; 0,040] 0,154 [0,137; 0,173]
SUMAR 0,057 [0,030; 0,095] 0,160 [0,143; 0,181]
VOX 0,124 [0,090; 0,172] 0,195 [0,162; 0,234]

Cada repetición usa un draw del posterior de los tau (tau_shock_draws.csv). Los demás partidos los obtienen así:

Partido Origen de sus tau
ERC, Junts, PNV, EH Bildu, BNG, CC Estimación en dos etapas, con valores fijos (tau_regionales.csv)
UPN Media cuadrática de los demás regionales, todo en tau_p
SALF Media cuadrática de los cuatro grandes
Podemos Los mismos valores que Sumar
Adelante Andalucía Los mismos valores que SALF
RESTO Sin shock

Tres efectos en la simulación real

Ver código
# ratio final de un partido en una provincia, repetición a repetición
ratio_final <- function(partido, provincia) {
  100 * sim$prov_voto[, provincia, partido] / sim$shares[, partido]
}

1. La incertidumbre del patrón. Este gráfico muestra el ratio final de VOX en las 52 provincias.

Ver código
provincias <- sim$prov_ref$provincia

vox_prov <- tibble(provincia = provincias) |>
  mutate(
    q05 = map_dbl(provincia, \(p) quantile(ratio_final("VOX", p), 0.05)),
    mediana = map_dbl(provincia, \(p) median(ratio_final("VOX", p))),
    q95 = map_dbl(provincia, \(p) quantile(ratio_final("VOX", p), 0.95))
  ) |>
  left_join(
    ref |> filter(partido == "VOX") |> select(provincia, ratio_ref = ratio),
    by = "provincia"
  ) |>
  mutate(provincia = fct_reorder(provincia, ratio_ref))

ggplot(vox_prov, aes(y = provincia)) +
  geom_vline(xintercept = 1, colour = "grey70", linewidth = 0.4) +
  geom_linerange(
    aes(xmin = q05, xmax = q95),
    colour = "#51962A",
    alpha = 0.45,
    linewidth = 0.8
  ) +
  geom_point(aes(x = mediana, shape = "Mediana simulada"), colour = "#51962A", size = 2) +
  geom_point(aes(x = ratio_ref, shape = "Ratio de referencia"), colour = "grey25", size = 2) +
  scale_shape_manual(
    name = NULL,
    values = c("Mediana simulada" = 16, "Ratio de referencia" = 5)
  ) +
  labs(x = "Ratio (voto en la provincia / voto en España)", y = NULL) +
  theme_minimal(base_size = 11) +
  theme(
    legend.position = "top",
    panel.grid.major.y = element_blank(),
    panel.grid.minor = element_blank()
  )
Gráfico de puntos con las 52 provincias ordenadas por el ratio de referencia de VOX. Cada provincia tiene un intervalo del 90 %, un punto con la mediana simulada y un rombo con el valor de referencia.
Figura 1: Ratio de VOX por provincia: valor de referencia y ratio final simulado, con mediana e intervalo del 90 %. Simulación del 3 de noviembre de 2026, 6.000 repeticiones.

2. La dispersión final es menor que tau. Si VOX sube en una provincia, la suma de la provincia sube, y la renormalización devuelve parte de esa subida. El efecto crece con el voto del partido en la provincia.

Ver código
celdas <- tribble(
  ~partido, ~provincia,
  "VOX",    "Granada",
  "VOX",    "Madrid",
  "VOX",    "Barcelona",
  "PP",     "Granada",
  "PP",     "Barcelona",
  "PSOE",   "Barcelona"
)

celdas |>
  left_join(
    tau_brms |>
      transmute(partido = familia, tau_total = sqrt(tau_c_med^2 + tau_p_med^2)),
    by = "partido"
  ) |>
  mutate(
    voto = map2_dbl(partido, provincia, \(f, p) 100 * median(sim$prov_voto[, p, f])),
    voto = num_es(voto, 1),
    sd_final = map2_dbl(partido, provincia, \(f, p) sd(log(ratio_final(f, p))))
  ) |>
  select(
    Partido = partido,
    Provincia = provincia,
    `Voto mediano (%)` = voto,
    `Tau total` = tau_total,
    `Desviación final` = sd_final
  ) |>
  tabla(3)
Tabla 7: Desviación típica del log-ratio final frente al tau total. Método: tau total = raíz de (tau_c² + tau_p²), con las medianas de cada tau. Simulación del 3 de noviembre de 2026.
Partido Provincia Voto mediano (%) Tau total Desviación final
VOX Granada 23,8 0,231 0,184
VOX Madrid 21,3 0,231 0,175
VOX Barcelona 11,5 0,231 0,208
PP Granada 33,5 0,176 0,138
PP Barcelona 12,9 0,176 0,165
PSOE Barcelona 31,1 0,155 0,108

3. El voto nacional se mueve un poco. El recentrado conserva el voto nacional antes de renormalizar. La renormalización y las reglas del paso 5 rompen esa igualdad en unas décimas.

Ver código
pesos_prov <- pesos$peso[match(provincias, pesos$provincia)]

tibble(Partido = c("PP", "PSOE", "VOX", "SALF")) |>
  mutate(
    `Voto del modelo` = map_dbl(Partido, \(f) mean(sim$shares[, f])),
    `Suma de provincias` = map_dbl(
      Partido,
      \(f) mean(100 * as.numeric(sim$prov_voto[, , f] %*% pesos_prov))
    ),
    `Diferencia (puntos)` = `Suma de provincias` - `Voto del modelo`
  ) |>
  tabla()
Tabla 8: Voto nacional del modelo frente a la suma ponderada del voto provincial, en %. Método: pesos en votos de la referencia, media de 6.000 repeticiones.
Partido Voto del modelo Suma de provincias Diferencia (puntos)
PP 30,71 30,52 -0,18
PSOE 27,18 26,87 -0,31
VOX 19,45 19,21 -0,25
SALF 1,91 1,91 0,00

No he separado qué parte de esta diferencia viene de cada ajuste. Probé a forzar la suma con raking, pero movía voto y escaños sin validación, así que lo descarté.

Por qué funciona mejor que la Dirichlet

El backtest repite el reparto provincial en las cinco últimas generales. Si el ruido está bien calibrado, el resultado real debe caer dentro del intervalo del 90 % cerca del 90 % de las veces.

Ver código
read_csv(
  here::here("2026/10/backtest_prov_comparacion.csv"),
  show_col_types = FALSE
) |>
  filter(variante %in% c("dirichlet (baseline)", "shock brms (draws)")) |>
  mutate(
    ruido = if_else(str_detect(variante, "dirichlet"), "Dirichlet", "Shock"),
    cobertura = 100 * cobertura
  ) |>
  select(Partido = familia, Celdas = celdas, ruido, Cobertura = cobertura, Ancho = ancho) |>
  pivot_wider(names_from = ruido, values_from = c(Cobertura, Ancho), names_sep = " ") |>
  tabla(1)
Tabla 9: Backtest provincial: cobertura del IC90 (% de celdas partido × provincia × elección) y ancho medio del intervalo, en puntos.
Partido Celdas Cobertura Dirichlet Cobertura Shock Ancho Dirichlet Ancho Shock
PP 255 73,3 96,1 6,9 14,6
PSOE 260 70,0 95,4 5,6 12,9
SUMAR 259 58,7 90,3 5,4 9,7
VOX 138 55,8 93,5 4,0 10,0
TOTAL 912 65,6 93,9 5,7 12,0

El shock acerca la cobertura al 90 %, a cambio de intervalos más anchos. Los tau se estiman con las mismas transiciones que prueba el backtest, así que también lo repito sin la transición probada (leave-one-transition-out, LOTO):

Ver código
read_csv(
  here::here("2026/10/backtest_prov_loto_resumen.csv"),
  show_col_types = FALSE
) |>
  mutate(cobertura = 100 * cobertura) |>
  select(
    `Elección` = eleccion,
    Variante = variante,
    Celdas = celdas,
    Cobertura = cobertura,
    `Ancho medio` = ancho_medio
  ) |>
  tabla(1)
Tabla 10: Cobertura del IC90 con los tau del ajuste completo (in-sample) y sin la transición probada (LOTO). El 20D no entra en el LOTO: su geografía viene del 11D, que no está en la calibración.
Elección Variante Celdas Cobertura Ancho medio
20d in-sample (oos) 154 83,8 12,7
26j loto 155 99,4 13,1
26j in-sample 155 99,4 13,2
28a loto 189 90,5 11,5
28a in-sample 189 89,9 11,2
10n loto 207 99,0 11,2
10n in-sample 207 99,0 11,5
23j loto 207 95,2 11,7
23j in-sample 207 95,7 11,8

LOTO e in-sample casi coinciden, así que los tau no están sobreajustados.

La Dirichlet

La primera versión, igual que en Andalucía, movía el patrón con una Dirichlet:

\[ \boldsymbol{\pi}^{(s)}_p \sim \text{Dirichlet}\left(\frac{V_p}{1000}\,\boldsymbol{\pi}^{23J}_p\right), \qquad r^{(s)}_{f,p} = r_{f,p} \cdot \frac{\pi^{(s)}_{f,p}}{\pi^{23J}_{f,p}} \]

Equivale a volver a votar el 23J con una muestra de \(V_p / 1000\) personas. Tenía tres problemas:

  1. El divisor de 1.000 era una decisión mía, sin respaldo en los datos.
  2. Las provincias grandes casi no se movían, y los datos no apoyan esa relación.
  3. No recogía un cambio común a toda una comunidad.

Sigue disponible con simular(modo_ruido = "dirichlet"), solo para comparar. Las Dirichlet del paso 5 son otra cosa: solo reparten el voto de las transferencias.

VOX en Santa Cruz de Tenerife

El 23J, VOX no tuvo lista al Congreso en esta provincia, porque sus candidatos renunciaron a última hora. Su ratio era 0, y hasta el 4 de noviembre de 2026 eso lo dejaba sin voto ni escaños allí en las simulaciones. El 29-N sí tiene candidato.

Ahora simular() usa su ratio del 10N: 11,54 % / 15,08 % = 0,765. Los CSV de referencia conservan el resultado real del 23J. Si otra familia nacional tuviera ratio 0 en alguna provincia, simular_escanos.R se detendría con un error.

Ver código
read_csv(
  here::here("metodologia/vox_tenerife_contrafactual.csv"),
  show_col_types = FALSE
) |>
  rename(Medida = medida, `Sin corregir` = sin_corregir, Corregido = corregido) |>
  tabla()
Tabla 11: Efecto de la corrección, con el mismo voto nacional y la misma semilla. Simulación del 3 de noviembre de 2026.
Medida Sin corregir Corregido
VOX en Tenerife: escaños medios 0,00 0,96
VOX en Tenerife: voto mediano (%) 0,00 13,44
PP en Tenerife: escaños medios 3,09 2,68
PSOE en Tenerife: escaños medios 2,67 2,29
VOX en España: escaños medios 68,31 68,10
PP en España: escaños medios 126,44 126,58
PSOE en España: escaños medios 108,52 108,60
PP + VOX en España: escaños medios 194,75 194,68
P(PP + VOX >= 176) (%) 94,77 94,58

El reparto de esta provincia cambia, pero los totales de España casi no se mueven. El voto nacional de VOX lo fija el modelo, así que lo que gana en Tenerife lo pierde en otras provincias. El script es vox_tenerife_contrafactual.R.

Los posts publicados antes de la corrección conservan sus cifras congeladas, con VOX en 0 en sus datos por provincia.

Limitaciones

  • Efecto PSC. Los tres fallos catalanes del PSOE en el 23J quedan fuera del intervalo incluso con el shock. Un cambio así requiere información actual por comunidad.
  • Una sola elección de referencia. La deriva desde 2023 solo entra como ruido de media cero.
  • Shocks independientes entre partidos. No he medido si sus cambios están relacionados en los datos.
  • El tau de Sumar está inflado. Parte de su cambio refleja cambios de coalición, no geografía.
  • Pocas transiciones. Por eso los tau de los regionales son valores fijos y frágiles.
  • Tau heredados. SALF, Podemos y Adelante Andalucía tienen poca historia propia.
  • RESTO no gana escaños. Pesa mucho en algunas provincias: su voto mediano es del 29 % en Soria y del 25 % en Teruel. Un partido nuevo sin datos previos también acabaría ahí.
  • Umbral algo más estricto que el legal. La ley cuenta los votos en blanco, y aquí no se simulan.

Dónde está el código

Fichero Qué contiene
simular_escanos.R simular(), aplicar_regla_mapa(), dhondt() y preparar_tau_simular()
shock_jerarquico.R Cambios de ratio, tau de los regionales y extraer_tau_draws()
backtest_prov_loto.R Ajuste brms de los tau (ajustar_tau_brm()) y LOTO
backtest_provincial.R Backtest provincial
coaliciones_izquierda_29N_provincias.csv Regla de cada provincia