El voto pendiente favorece a Sánchez

Corrección de sesgo urbano-rural en el escrutinio parcial · Validación con conteos rápidos Ipsos/Transparencia y Datum/América

Autor/a

Cornejo, Hugo

Fecha de publicación

15 de abril de 2026

1 Contexto y punto de corte del análisis

El presente análisis se realiza sobre el escrutinio parcial publicado por la ONPE el 14 de abril de 2026 al 86.0 % de actas, correspondiente a la primera vuelta de las Elecciones Generales. Se trata de un corte intermedio del escrutinio, no del cierre del día.

A ese momento, los resultados mostraban a Keiko Fujimori (Fuerza Popular) en primer lugar con 16.84 % del total de votos válidos, seguida de López Aliaga (Renovación Popular, 12.12 %), Sánchez (Juntos por el Perú, 11.58 %), Nieto (Partido del Buen Gobierno, 11.29 %), Belmont (Partido Cívico Obras, 10.15 %), Álvarez (País para Todos, 7.87 %) y López Chau (Ahora Nación, 7.47 %).

Estos porcentajes, calculados sobre el universo completo de votos válidos, son directamente comparables con los conteos rápidos disponibles:

  • Ipsos/Transparencia (1,037 actas, al 95.7 %, NC 95 %): Keiko 17.1 %, Sánchez 12.4 %, Aliaga 11.3 %, Nieto 10.7 %, Belmont 10.2 %, Álvarez 8.0 %, López Chau 7.4 %.
  • Datum/América TV (317,768 votos válidos, muestreo aleatorio): Keiko 16.8 %, Aliaga 12.9 %, Nieto 11.6 %, Belmont 10.1 %, Sánchez 9.4 %, Álvarez 8.1 %, López Chau 7.7 %.

La brecha entre el escrutinio parcial y los conteos rápidos responde a un sesgo sistemático de orden de llegada de actas: las mesas urbanas —con mayor conectividad— transmiten sus resultados antes que las rurales, sesgando el escrutinio acumulado hacia el perfil de voto urbano.

Nota sobre el voto en el extranjero. Al 31.105 % de mesas del exterior contabilizadas, asistieron 119,000 electores (31.6 % de participación) mientras que 257,400 no se presentaron. De los que votaron, 83,663 lo hicieron por los 7 candidatos principales y ~35,000 por otros candidatos, blancos o nulos. Aplicando la misma tasa de participación y distribución al 68.895 % de mesas pendientes, se proyectan ~185,000 votos adicionales para los 7 candidatos. López Aliaga concentra el 33.4 % de ese voto exterior, lo que le sumaría hasta 0.42 pp adicionales — insuficiente para cerrar el margen de ~3.3 pp que lo separa de Sánchez en la proyección.


2 Datos

2.1 Escrutinio ONPE al 86.0 % — 7 candidatos principales

Mostrar código R
escrutinio <- tribble(
  ~dpto,           ~KEIKO,   ~ALIAGA,  ~NIETO,  ~SANCHEZ,  ~BELMONT, ~ALVAREZ, ~LOPEZCHAU, ~actas,
  "AMAZONAS",       22605,     4770,    4996,    37556,    13605,    3291,     7773, 0.68388,
  "ANCASH",         80982,    27235,   33683,    70311,    46113,   45240,    41084, 0.84706,
  "APURIMAC",       12572,     5808,    6835,    73366,    25639,    2686,    19723, 0.89749,
  "AREQUIPA",       61941,    90389,  157720,    85097,    92257,   70384,    78673, 0.96014,
  "AYACUCHO",       21661,     7363,   14961,    82829,    38578,    6214,    38946, 0.93684,
  "CAJAMARCA",      70739,    17551,   25014,   215587,    57591,   16468,    23757, 0.77382,
  "CALLAO",        113765,    82645,   82779,    16503,    44797,   66679,    32730, 0.95031,
  "CUSCO",          38793,    31378,   59163,   141194,    99351,   19057,    95660, 0.91162,
  "HUANCAVELICA",   11371,     3789,    5253,    70093,    21824,    2788,    15085, 0.93166,
  "HUANUCO",        46189,    18262,   14503,    88140,    43020,   16961,    18157, 0.86373,
  "ICA",            66039,    32231,   33094,    24499,    33599,   38543,    21757, 0.66926,
  "JUNIN",          97692,    45108,   48048,    66976,    63525,   43092,    65663, 0.89488,
  "LA LIBERTAD",   168356,    69779,   82633,    78044,    59005,   66325,    34196, 0.89155,
  "LAMBAYEQUE",    160469,    53673,   64337,    62162,    44619,   57673,    27463, 0.90669,
  "LIMA",         1002078,  1124705,  848859,   182927,   512699,  500455,   385598, 0.92126,
  "LORETO",         77460,    18850,   10413,    22754,    11812,   33825,    12187, 0.76567,
  "MADRE DE DIOS",   7841,     2044,    3165,    10348,     7700,    3828,     4515, 0.63314,
  "MOQUEGUA",        7154,     6313,   11316,    13912,    13211,    5854,    11452, 0.94983,
  "PASCO",          19546,     6791,    4732,    19224,    12485,    4279,     9425, 0.88529,
  "PIURA",         177850,    47355,   60422,    62405,    48003,   69163,    30628, 0.70820,
  "PUNO",           24163,    12010,   25903,   152509,   109698,   10211,    70991, 0.94760,
  "SAN MARTIN",     73785,    18565,   14533,    74332,    35288,   15533,    13586, 0.79597,
  "TACNA",          14296,    12980,   23970,    24711,    30329,   15223,    20758, 0.94236,
  "TUMBES",         34177,     5956,    5596,     6916,     4916,   14964,     4990, 0.90665,
  "UCAYALI",        49699,     9641,    7882,    17505,    13486,   18222,     6680, 0.73210
)

exterior <- tibble(
  KEIKO=15922, ALIAGA=27924, NIETO=10789, SANCHEZ=2490,
  BELMONT=8957, ALVAREZ=10636, LOPEZCHAU=6945
)

urb <- tribble(
  ~dpto,             ~pct_urb,
  "AMAZONAS",          42.3,
  "ANCASH",            64.0,
  "APURIMAC",          46.6,
  "AREQUIPA",          91.6,
  "AYACUCHO",          58.7,
  "CAJAMARCA",         36.2,
  "CALLAO",            99.9,
  "CUSCO",             60.7,
  "HUANCAVELICA",      32.6,
  "HUANUCO",           52.6,
  "ICA",               92.2,
  "JUNIN",             70.8,
  "LA LIBERTAD",       78.9,
  "LAMBAYEQUE",        80.9,
  "LIMA",              98.1,
  "LORETO",            68.9,
  "MADRE DE DIOS",     83.1,
  "MOQUEGUA",          87.1,
  "PASCO",             63.5,
  "PIURA",             79.3,
  "PUNO",              54.0,
  "SAN MARTIN",        68.1,
  "TACNA",             90.0,
  "TUMBES",            93.7,
  "UCAYALI",           80.8
)

cands       <- c("KEIKO","ALIAGA","NIETO","SANCHEZ","BELMONT","ALVAREZ","LOPEZCHAU")
total_otros <- 3334813   # suma de los 29 candidatos restantes al 86%

df <- escrutinio |>
  left_join(urb, by = "dpto") |>
  mutate(total = rowSums(across(all_of(cands))), urb_f = pct_urb / 100)

act           <- map_dbl(cands, ~ sum(df[[.x]]) + exterior[[.x]]) |> set_names(cands)
total_act_7   <- sum(act)
total_act_all <- total_act_7 + total_otros

tibble(
  candidato = c("Keiko Fujimori","López Aliaga","Roberto Sánchez","Jorge Nieto",
                "Ricardo Belmont","Carlos Álvarez","Alfonso López Chau"),
  partido   = c("Fuerza Popular","Renovación Popular","Juntos por el Perú",
                "Partido del Buen Gobierno","Partido Cívico Obras",
                "País para Todos","Ahora Nación"),
  votos     = as.numeric(act),
  pct       = as.numeric(act) / total_act_all * 100
) |>
  arrange(desc(pct)) |>
  mutate(votos = number(votos, big.mark = ","),
         pct   = paste0(round(pct, 2), "%")) |>
  kable(col.names = c("Candidato","Partido","Votos (86 % actas)","% s/total validos"),
        caption   = "Tabla 1. Escrutinio parcial ONPE al 86.0 %") |>
  kst(font_size = 10)
Tabla 1. Escrutinio parcial ONPE al 86.0 %
Candidato Partido Votos (86 % actas) % s/total validos
Keiko Fujimori Fuerza Popular 2,477,145 16.84%
López Aliaga Renovación Popular 1,783,115 12.12%
Jorge Nieto Partido del Buen Gobierno 1,702,390 11.58%
Roberto Sánchez Juntos por el Perú 1,660,599 11.29%
Ricardo Belmont Partido Cívico Obras 1,492,107 10.15%
Carlos Álvarez País para Todos 1,157,594 7.87%
Alfonso López Chau Ahora Nación 1,098,422 7.47%

Todos los porcentajes se expresan sobre el universo completo de votos válidos (incluidos los 29 candidatos restantes que suman 22.65 %), para ser directamente comparables con los conteos rápidos de Ipsos y Datum.

2.2 Candidatos con menor probabilidad de segunda vuelta

Los 29 candidatos fuera del top 7 suman 3,334,813 votos al 86 % (22.65 % del total válido); ninguno supera individualmente el 3.5 %.

Mostrar código R
tribble(
  ~Candidato,               ~Partido,                    ~Votos,
  "M.S. Pérez Tello",       "Primero la Gente",           514121,
  "Carlos Espá",            "SíCreo",                     506346,
  "Fernando Olivera",       "Frente Esperanza 2021",      276723,
  "José Luna Gálvez",       "Podemos Perú",               227727,
  "Yonhy Lescano",          "Cooperación Popular",        196204,
  "César Acuña",            "Alianza para el Progreso",   163935,
  "Pitter Valderrama",      "Partido Aprista Peruano",    141023,
  "George Forsyth",         "Somos Perú",                 129813,
  "Herbert Caller",         "Patriótico del Perú",        126088,
  "Ronald Atencio",         "Alianza Venceremos",         124570,
  "Mario Vizcarra",         "Perú Primero",               124219,
  "Rosario Fernández",      "Un Camino Diferente",        109760,
  "Charlie Carrasco",       "Demócrata Unido Perú",       104060,
  "Vladimir Cerrón",        "Perú Libre",                  87139,
  "Mesías Guevara",         "Partido Morado",               72919,
  "Roberto Chiabra",        "Unidad Nacional",              60034,
  "Paul Jaimes",            "Progresemos",                  58082,
  "Wolfgang Grozo",         "Integridad Democrática",       56598,
  "Álex González",          "Demócrata Verde",              54917,
  "Rafael Belaunde",        "Libertad Popular",             35760,
  "José Williams",          "Avanza País",                  28496,
  "F. Diez-Canseco",        "Perú Acción",                  27327,
  "Fiorella Molinelli",     "Fuerza y Libertad",            23875,
  "Álvaro Paz de la Barra", "Fe en el Perú",                20264,
  "Armando Massé",          "Democrático Federal",          18879,
  "Antonio Ortiz",          "Salvemos al Perú",             15009,
  "Walter Chirinos",        "PRIN",                         12469,
  "Napoleón Becerra",       "PTE Perú",                      9953,
  "Carlos Jaico",           "Perú Moderno",                  8503
) |>
  mutate(Votos = number(Votos, big.mark = ",")) |>
  kable(caption = "Tabla 2. Candidatos fuera del top 7") |>
  kst(font_size = 9)
Tabla 2. Candidatos fuera del top 7
Candidato Partido Votos
M.S. Pérez Tello Primero la Gente 514,121
Carlos Espá SíCreo 506,346
Fernando Olivera Frente Esperanza 2021 276,723
José Luna Gálvez Podemos Perú 227,727
Yonhy Lescano Cooperación Popular 196,204
César Acuña Alianza para el Progreso 163,935
Pitter Valderrama Partido Aprista Peruano 141,023
George Forsyth Somos Perú 129,813
Herbert Caller Patriótico del Perú 126,088
Ronald Atencio Alianza Venceremos 124,570
Mario Vizcarra Perú Primero 124,219
Rosario Fernández Un Camino Diferente 109,760
Charlie Carrasco Demócrata Unido Perú 104,060
Vladimir Cerrón Perú Libre 87,139
Mesías Guevara Partido Morado 72,919
Roberto Chiabra Unidad Nacional 60,034
Paul Jaimes Progresemos 58,082
Wolfgang Grozo Integridad Democrática 56,598
Álex González Demócrata Verde 54,917
Rafael Belaunde Libertad Popular 35,760
José Williams Avanza País 28,496
F. Diez-Canseco Perú Acción 27,327
Fiorella Molinelli Fuerza y Libertad 23,875
Álvaro Paz de la Barra Fe en el Perú 20,264
Armando Massé Democrático Federal 18,879
Antonio Ortiz Salvemos al Perú 15,009
Walter Chirinos PRIN 12,469
Napoleón Becerra PTE Perú 9,953
Carlos Jaico Perú Moderno 8,503

2.3 Conteos rápidos de referencia

Mostrar código R
tribble(
  ~Candidato,          ~`Ipsos / Transparencia`,  ~`Datum / America TV`,
  "Keiko Fujimori",    "17.1 % +/- 1.0",          "16.8 %",
  "Roberto Sánchez",   "12.4 % +/- 1.3",           "9.4 %",
  "López Aliaga",      "11.3 % +/- 1.2",           "12.9 %",
  "Jorge Nieto",       "10.7 % +/- 0.9",           "11.6 %",
  "Ricardo Belmont",   "10.2 % +/- 0.5",           "10.1 %",
  "Carlos Álvarez",     "8.0 % +/- 0.5",            "8.1 %",
  "López Chau",         "7.4 % +/- 0.5",            "7.7 %",
  "Otros (29)",        "22.9 %",                    "23.4 %"
) |>
  kable(caption = "Tabla 3. Conteos rapidos del 12 de abril de 2026") |>
  kst(font_size = 10)
Tabla 3. Conteos rapidos del 12 de abril de 2026
Candidato Ipsos / Transparencia Datum / America TV
Keiko Fujimori 17.1 % +/- 1.0 16.8 %
Roberto Sánchez 12.4 % +/- 1.3 9.4 %
López Aliaga 11.3 % +/- 1.2 12.9 %
Jorge Nieto 10.7 % +/- 0.9 11.6 %
Ricardo Belmont 10.2 % +/- 0.5 10.1 %
Carlos Álvarez 8.0 % +/- 0.5 8.1 %
López Chau 7.4 % +/- 0.5 7.7 %
Otros (29) 22.9 % 23.4 %

Divergencia clave. La mayor brecha entre las empresas encuestadoras está en Sánchez (Ipsos 12.4 % vs Datum 9.4 %) y Aliaga (Datum 12.9 % vs Ipsos 11.3 %). Ipsos emplea muestreo probabilístico polietápico estratificado por región y zona urbano/rural, garantizando representación de localidades rurales donde Sánchez domina (33.8 % del voto rural según su desagregado). Datum usa muestreo aleatorio simple, que puede subrepresentar esas zonas.


3 modelo de corrección del sesgo urbano con simulación

3.1 Hipótesis de orden de llegada de actas

Las mesas en zonas más urbanizadas —con mejor conectividad— entregan sus actas antes, sesgando el escrutinio acumulado hacia el perfil de voto urbano.

Para cuantificar el sesgo se usa el porcentaje de población urbana por departamento del Censo Nacional 2017 (INEI). Para el departamento \(d\) con fracción de actas contadas \(\alpha_d\) y fracción urbana \(u_d\):

\[ \text{FUC}_d = \begin{cases} 1 & \text{si } \alpha_d \leq u_d \\ u_d / \alpha_d & \text{si } \alpha_d > u_d \end{cases} \qquad \text{FRC}_d = 1 - \text{FUC}_d \]

La fracción del universo aún pendiente se descompone en:

\[ f^{urb}_d = \max(0,\; u_d - \alpha_d) \qquad f^{rur}_d = (1 - \alpha_d) - f^{urb}_d \]

Mostrar código R
df <- df |>
  mutate(
    FUC        = if_else(actas <= urb_f, 1, urb_f / actas),
    FRC        = 1 - FUC,
    f_urb_falt = pmax(0, urb_f - actas),
    f_rur_falt = (1 - actas) - pmax(0, urb_f - actas)
  )

df |>
  select(dpto, actas, pct_urb, FUC, FRC, f_urb_falt, f_rur_falt) |>
  mutate(across(c(FUC, FRC, f_urb_falt, f_rur_falt), ~ round(.x, 3)),
         actas   = paste0(round(actas * 100, 1), "%"),
         pct_urb = paste0(pct_urb, "%")) |>
  kable(col.names = c("Dpto","Actas","% Urb","FUC","FRC","Pend. urb","Pend. rur"),
        caption   = "Tabla 4. Descomposicion urbano/rural por departamento") |>
  kst(font_size = 8)
Tabla 4. Descomposicion urbano/rural por departamento
Dpto Actas % Urb FUC FRC Pend. urb Pend. rur
AMAZONAS 68.4% 42.3% 0.619 0.381 0.000 0.316
ANCASH 84.7% 64% 0.756 0.244 0.000 0.153
APURIMAC 89.7% 46.6% 0.519 0.481 0.000 0.103
AREQUIPA 96% 91.6% 0.954 0.046 0.000 0.040
AYACUCHO 93.7% 58.7% 0.627 0.373 0.000 0.063
CAJAMARCA 77.4% 36.2% 0.468 0.532 0.000 0.226
CALLAO 95% 99.9% 1.000 0.000 0.049 0.001
CUSCO 91.2% 60.7% 0.666 0.334 0.000 0.088
HUANCAVELICA 93.2% 32.6% 0.350 0.650 0.000 0.068
HUANUCO 86.4% 52.6% 0.609 0.391 0.000 0.136
ICA 66.9% 92.2% 1.000 0.000 0.253 0.078
JUNIN 89.5% 70.8% 0.791 0.209 0.000 0.105
LA LIBERTAD 89.2% 78.9% 0.885 0.115 0.000 0.108
LAMBAYEQUE 90.7% 80.9% 0.892 0.108 0.000 0.093
LIMA 92.1% 98.1% 1.000 0.000 0.060 0.019
LORETO 76.6% 68.9% 0.900 0.100 0.000 0.234
MADRE DE DIOS 63.3% 83.1% 1.000 0.000 0.198 0.169
MOQUEGUA 95% 87.1% 0.917 0.083 0.000 0.050
PASCO 88.5% 63.5% 0.717 0.283 0.000 0.115
PIURA 70.8% 79.3% 1.000 0.000 0.085 0.207
PUNO 94.8% 54% 0.570 0.430 0.000 0.052
SAN MARTIN 79.6% 68.1% 0.856 0.144 0.000 0.204
TACNA 94.2% 90% 0.955 0.045 0.000 0.058
TUMBES 90.7% 93.7% 1.000 0.000 0.030 0.063
UCAYALI 73.2% 80.8% 1.000 0.000 0.076 0.192

3.2 Regresión por mínimos cuadrados ponderados (WLS)

Para estimar el voto esperado en la fracción faltante se ajusta una regresión lineal ponderada por tamaño del departamento:

\[ p_{c,d} = \alpha_c + \beta_c \cdot u_d + \varepsilon_{c,d} \]

donde \(p_{c,d}\) es la fracción de voto del candidato \(c\) en el departamento \(d\), \(u_d\) es el porcentaje urbano y el peso es \(w_d\) = total de votos del departamento. El estimador es:

\[ \hat{\beta}_c = (X^\top W X)^{-1} X^\top W y_c \]

Un \(\beta_c > 0\) indica perfil urbano; \(\beta_c < 0\) indica perfil rural. El \(R^2\) mide cuánta variación interdepartamental del voto explica la urbanización.

Mostrar código R
wls_fit <- function(cand, data) {
  df_c <- data |> mutate(y = .data[[cand]] / total, w = total)
  fit  <- lm(y ~ urb_f, data = df_c, weights = w)
  s    <- summary(fit)
  list(alpha = coef(fit)[1], beta = coef(fit)[2],
       r2 = s$r.squared, pval = coef(s)[2, 4])
}

coefs_list <- map(cands, ~ wls_fit(.x, df)) |> set_names(cands)

coefs_tbl <- tibble(
  cand_id   = cands,
  candidato = c("Keiko Fujimori","López Aliaga","Jorge Nieto","Roberto Sánchez",
                "Ricardo Belmont","Carlos Álvarez","López Chau"),
  alpha  = map_dbl(coefs_list, "alpha"),
  beta   = map_dbl(coefs_list, "beta"),
  r2     = map_dbl(coefs_list, "r2"),
  pval   = map_dbl(coefs_list, "pval"),
  perfil = case_when(beta >  0.02 ~ "Urbano",
                     beta < -0.02 ~ "Rural",
                     TRUE         ~ "Neutro")
)

coefs_tbl |>
  mutate(across(c(alpha, beta, r2), ~ round(.x, 4)),
         pval = scales::pvalue(pval)) |>
  select(candidato, alpha, beta, r2, pval, perfil) |>
  kable(col.names = c("Candidato","alpha","beta","R2","p-valor","Perfil"),
        caption   = "Tabla 5. Coeficientes WLS") |>
  kst(font_size = 10)
Tabla 5. Coeficientes WLS
Candidato alpha beta R2 p-valor Perfil
Keiko Fujimori 0.1194 0.1201 0.0744 0.187 Urbano
López Aliaga -0.1557 0.3788 0.7808 <0.001 Urbano
Jorge Nieto -0.0614 0.2527 0.7534 <0.001 Urbano
Roberto Sánchez 0.7289 -0.7040 0.9215 <0.001 Rural
Ricardo Belmont 0.2283 -0.1180 0.3084 0.004 Rural
Carlos Álvarez -0.0085 0.1341 0.4705 <0.001 Urbano
López Chau 0.1491 -0.0638 0.1003 0.123 Rural
Mostrar código R
coefs_tbl |>
  mutate(candidato = fct_reorder(candidato, beta)) |>
  ggplot(aes(x = beta, y = candidato, fill = perfil)) +
  geom_col(width = 0.6, show.legend = FALSE) +
  geom_vline(xintercept = 0, linewidth = 0.4, color = "grey30") +
  geom_text(aes(label = paste0("R2=", round(r2, 2)),
                x     = ifelse(beta >= 0, beta + 0.008, beta - 0.008),
                hjust = ifelse(beta >= 0, 0, 1)),
            size = 3.2, color = "grey25") +
  scale_fill_manual(values = c("Rural"="#1D9E75","Urbano"="#378ADD","Neutro"="#888780")) +
  scale_x_continuous(limits = c(-0.80, 0.50)) +
  labs(title   = "Perfil urbano/rural de cada candidato",
       subtitle = "Coeficiente beta — WLS ponderada por tamaño departamento",
       x = "beta (negativo = rural, positivo = urbano)", y = NULL,
       caption = "Fuente: ONPE 86 % actas, INEI Censo 2017") +
  theme_elec()
Figura 1: Figura 1. Gradiente urbano/rural por candidato (beta WLS).

3.3 Proyección de votos faltantes

El voto esperado del candidato \(c\) en la fracción faltante del departamento \(d\) es:

\[ \hat{V}^{extra}_{c,d} = \frac{V_d}{\alpha_d} \cdot f^{urb}_d \cdot \hat{p}^{urb}_c + \frac{V_d}{\alpha_d} \cdot f^{rur}_d \cdot \hat{p}^{rur}_c \]

donde \(\hat{p}^{urb}_c = \text{clip}(\hat\alpha_c + \hat\beta_c)\) y \(\hat{p}^{rur}_c = \text{clip}(\hat\alpha_c)\), acotando entre 0 y 1.

El total proyectado agrega votos actuales, extras por departamento y el exterior. Con el 68.895 % de mesas del exterior pendientes, la participación observada de 31.6 % y el 70.3 % de votos válidos hacia los 7 candidatos, se proyectan ~185,000 votos adicionales en el exterior:

\[ \hat{V}^{final}_c = V^{act}_c + \sum_{d=1}^{25} \hat{V}^{extra}_{c,d} + \frac{V^{ext,act}_c}{V^{ext,act}_{total}} \times 185{,}307 \]

Los porcentajes se expresan sobre el universo completo asumiendo que los 29 candidatos restantes mantienen su participación observada (22.65 %):

\[ \hat{p}^{final}_c = \frac{\hat{V}^{final}_c}{\hat{V}^{final}_{top7} \;/\; (1 - 0.2265)} \]

Mostrar código R
ext_act   <- c(KEIKO=15922, ALIAGA=27924, NIETO=10789, SANCHEZ=2490,
               BELMONT=8957, ALVAREZ=10636, LOPEZCHAU=6945)
ext_total <- sum(ext_act)
# Votos pendientes exterior: 68.895% mesas restantes con participacion 31.6%
# y 70.3% de votos validos hacia los 7 candidatos → 185,307 votos pendientes
ext_falt  <- 185307L

ve <- setNames(rep(0, length(cands)), cands)
for (i in seq_len(nrow(df))) {
  r     <- df[i, ]
  v_tot <- r$total / r$actas
  v_urb <- v_tot * r$f_urb_falt
  v_rur <- v_tot * r$f_rur_falt
  for (c in cands) {
    pu    <- max(0, min(1, coefs_list[[c]]$alpha + coefs_list[[c]]$beta))
    pr    <- max(0, min(1, coefs_list[[c]]$alpha))
    ve[c] <- ve[c] + v_urb * pu + v_rur * pr
  }
}
for (c in cands) ve[c] <- ve[c] + ext_act[c] / ext_total * ext_falt

fin          <- act + ve
gran_fin7    <- sum(fin)
pct_otros    <- total_otros / total_act_all
gran_fin_all <- gran_fin7 / (1 - pct_otros)

proj_tbl <- tibble(
  cand_id   = cands,
  candidato = c("Keiko Fujimori","López Aliaga","Jorge Nieto","Roberto Sánchez",
                "Ricardo Belmont","Carlos Álvarez","López Chau"),
  votos_act = as.numeric(act),
  pct_act   = as.numeric(act) / total_act_all * 100,
  votos_fin = as.numeric(fin),
  pct_fin   = as.numeric(fin) / gran_fin_all * 100,
  delta     = pct_fin - pct_act
) |>
  arrange(desc(pct_fin))

proj_tbl |>
  mutate(votos_act = number(round(votos_act), big.mark = ","),
         votos_fin = number(round(votos_fin), big.mark = ","),
         pct_act   = paste0(round(pct_act, 2), "%"),
         pct_fin   = paste0(round(pct_fin, 2), "%"),
         delta     = ifelse(delta > 0,
                            paste0("+", round(delta, 2), " pp"),
                            paste0(round(delta, 2), " pp"))) |>
  select(-cand_id) |>
  kable(col.names = c("Candidato","Votos act.","% act.",
                      "Votos proy.","% proy.","Delta"),
        caption   = "Tabla 6. Proyeccion con corrección de sesgos sobre universo completo de votos validos") |>
  kst(font_size = 10)
Tabla 6. Proyeccion con corrección de sesgos sobre universo completo de votos validos
Candidato Votos act. % act. Votos proy. % proy. Delta
Keiko Fujimori 2,477,145 16.84% 2,755,190 15.99% -0.85 pp
Roberto Sánchez 1,702,390 11.58% 2,472,358 14.35% +2.78 pp
López Aliaga 1,783,115 12.12% 1,956,413 11.36% -0.77 pp
Ricardo Belmont 1,492,107 10.15% 1,802,601 10.46% +0.32 pp
Jorge Nieto 1,660,599 11.29% 1,780,034 10.33% -0.96 pp
López Chau 1,098,422 7.47% 1,310,223 7.61% +0.14 pp
Carlos Álvarez 1,157,594 7.87% 1,243,859 7.22% -0.65 pp

3.4 Intervalos de confianza por bootstrap

Se aplica bootstrap no paramétrico con 2,000 iteraciones sobre los departamentos. En cada iteración se remuestrea con reposición la tabla de 25 departamentos, se reestima la WLS y se recalculan los votos proyectados. Los percentiles 5 % y 95 % definen el intervalo de confianza al 90 %.

Mostrar código R
set.seed(42)
B    <- 2000
n    <- nrow(df)
boot <- matrix(NA_real_, B, length(cands), dimnames = list(NULL, cands))

for (b in seq_len(B)) {
  db      <- df[sample(n, n, replace = TRUE), ]
  coefs_b <- map(cands, function(c) {
    df_c <- db |> mutate(y = .data[[c]] / total, w = total)
    tryCatch({
      fit <- lm(y ~ urb_f, data = df_c, weights = w)
      list(alpha = coef(fit)[1], beta = coef(fit)[2])
    }, error = function(e) coefs_list[[c]])
  }) |> set_names(cands)

  ve_b <- setNames(rep(0, length(cands)), cands)
  for (i in seq_len(nrow(df))) {
    r     <- df[i, ]
    v_tot <- r$total / r$actas
    v_urb <- v_tot * r$f_urb_falt
    v_rur <- v_tot * r$f_rur_falt
    for (c in cands) {
      pu      <- max(0, min(1, coefs_b[[c]]$alpha + coefs_b[[c]]$beta))
      pr      <- max(0, min(1, coefs_b[[c]]$alpha))
      ve_b[c] <- ve_b[c] + v_urb * pu + v_rur * pr
    }
  }
  for (c in cands) ve_b[c] <- ve_b[c] + ext_act[c] / ext_total * ext_falt

  fin_b      <- act + ve_b
  gran_b_all <- sum(fin_b) / (1 - pct_otros)
  boot[b, ]  <- fin_b / gran_b_all * 100
}

ic_tbl <- tibble(
  cand_id   = cands,
  candidato = c("Keiko Fujimori","López Aliaga","Jorge Nieto","Roberto Sánchez",
                "Ricardo Belmont","Carlos Álvarez","López Chau"),
  pct_fin   = as.numeric(fin) / gran_fin_all * 100,
  ic_lo     = apply(boot, 2, quantile, 0.05),
  ic_hi     = apply(boot, 2, quantile, 0.95)
) |>
  arrange(desc(pct_fin))

ic_tbl |>
  mutate(pct_fin = paste0(round(pct_fin, 2), "%"),
         ic      = paste0("[", round(ic_lo, 2), "% - ", round(ic_hi, 2), "%]")) |>
  select(candidato, pct_fin, ic) |>
  kable(col.names = c("Candidato","% proyectado","IC 90 % bootstrap"),
        caption   = "Tabla 7. Proyeccion con correciones de sesgo con intervalos de confianza al 90 %") |>
  kst(font_size = 10)
Tabla 7. Proyeccion con correciones de sesgo con intervalos de confianza al 90 %
Candidato % proyectado IC 90 % bootstrap
Keiko Fujimori 15.99% [15.44% - 16.57%]
Roberto Sánchez 14.35% [13.92% - 14.66%]
López Aliaga 11.36% [11.13% - 11.42%]
Ricardo Belmont 10.46% [10.17% - 10.84%]
Jorge Nieto 10.33% [10.24% - 10.43%]
López Chau 7.61% [7.26% - 8.04%]
Carlos Álvarez 7.22% [7.17% - 7.41%]

4 Validación contra conteos rápidos

Mostrar código R
ref <- tribble(
  ~candidato,          ~ipsos, ~me_i, ~datum, ~me_d,
  "Keiko Fujimori",     17.1,   1.0,   16.8,   1.0,
  "Roberto Sánchez",    12.4,   1.3,    9.4,   1.0,
  "López Aliaga",       11.3,   1.2,   12.9,   1.0,
  "Jorge Nieto",        10.7,   0.9,   11.6,   1.0,
  "Ricardo Belmont",    10.2,   0.5,   10.1,   1.0,
  "Carlos Álvarez",      8.0,   0.5,    8.1,   1.0,
  "López Chau",          7.4,   0.5,    7.7,   1.0
)

val <- ic_tbl |>
  left_join(ref, by = "candidato") |>
  mutate(candidato = fct_reorder(candidato, pct_fin))

val_long <- val |>
  pivot_longer(c(pct_fin, ipsos, datum), names_to = "fuente", values_to = "pct") |>
  mutate(fuente = recode(fuente,
    pct_fin = "Modelo de corrección del sesgo",
    ipsos   = "Ipsos / Transparencia",
    datum   = "Datum / America TV"
  ))

ggplot(val, aes(y = candidato)) +
  geom_rect(aes(xmin = ic_lo, xmax = ic_hi,
                ymin = as.numeric(candidato) - 0.44,
                ymax = as.numeric(candidato) + 0.44),
            fill = "#533AB7", alpha = 0.10) +
  geom_rect(aes(xmin = ipsos - me_i, xmax = ipsos + me_i,
                ymin = as.numeric(candidato) - 0.28,
                ymax = as.numeric(candidato) + 0.28),
            fill = "#D85A30", alpha = 0.18) +
  geom_rect(aes(xmin = datum - me_d, xmax = datum + me_d,
                ymin = as.numeric(candidato) - 0.14,
                ymax = as.numeric(candidato) + 0.14),
            fill = "#0F6E56", alpha = 0.22) +
  geom_point(data = val_long,
             aes(x = pct, color = fuente, shape = fuente), size = 3.5) +
  scale_color_manual(values = c("Modelo corrección del sesgo"      = "#533AB7",
                                "Ipsos / Transparencia" = "#D85A30",
                                "Datum / America TV"    = "#0F6E56")) +
  scale_shape_manual(values = c(16, 17, 15)) +
  scale_x_continuous(labels = label_percent(scale = 1, accuracy = 1),
                     limits = c(5, 21), breaks = seq(6, 20, 2)) +
  labs(title    = "Proyeccion con corrección de sesgos vs conteos rapidos",
       subtitle = "Todos los porcentajes sobre universo completo de votos validos",
       x = "% de votos validos", y = NULL,
       caption  = "Fuentes: ONPE 86 % actas (14 abr 2026), INEI Censo 2017, Ipsos/Transparencia, Datum/America TV") +
  theme_elec() +
  theme(legend.position = "top")
Figura 2: Figura 2. Proyeccion con correcióndel sesgo vs conteos rapidos. Franja ancha = IC 90 %. Franjas medias = margenes de error declarados.

5 Resultados y conclusiones

5.1 Proyección final

Mostrar código R
plot_df <- proj_tbl |>
  left_join(ic_tbl |> select(cand_id, ic_lo, ic_hi), by = "cand_id") |>
  mutate(candidato = fct_reorder(candidato, pct_fin))

ggplot(plot_df) +
  geom_col(aes(x = pct_act, y = candidato),
           fill = "grey82", width = 0.72, alpha = 0.7) +
  geom_col(aes(x = pct_fin, y = candidato, fill = cand_id), width = 0.40) +
  geom_errorbarh(aes(xmin = ic_lo, xmax = ic_hi, y = candidato),
                 height = 0.22, linewidth = 0.7, color = "grey25") +
  geom_text(aes(x = pct_fin + 0.3, y = candidato,
                label = paste0(round(pct_fin, 1), "%")),
            size = 3.3, hjust = 0, color = "grey20") +
  scale_fill_manual(values = colores, guide = "none") +
  scale_x_continuous(labels = label_percent(scale = 1, accuracy = 1),
                     expand  = expansion(mult = c(0, 0.14))) +
  labs(title    = "Escrutinio parcial (86 %) vs proyeccion con corrección de sesgos",
       subtitle = "Barras grises = actual, barras coloreadas = proyeccion, segmentos = IC 90 %",
       x = "% sobre universo completo de votos validos", y = NULL,
       caption  = "Modelo WLS, prior % urbano INEI 2017, bootstrap 2,000 iter. Punto de corte: 14 abr 2026, 86.0 % actas") +
  theme_elec()
Figura 3: Figura 3. Escrutinio parcial (barras grises) vs proyeccion con corrección de sesgos (coloreadas) con IC 90 %.

5.2 Síntesis de hallazgos

1. Con el 86 % de actas el modelo converge claramente hacia los conteos rápidos. Para Keiko, Belmont y Nieto la proyección es casi exacta respecto a Ipsos. EstoEsto es consistente con la hipótesis de orden de llegada de actas y sugiere que el modelo captura el sesgo urbano del escrutinio parcial.

2. Sánchez mantiene el mayor sesgo de subestimación. Con beta = -0.704 y R2 = 0.922, la urbanización explica una proporción muy alta de la variación interdepartamental de su voto. El modelo lo proyecta en 14.35 %, frente al 11.58 % actual y al 12.4 % de Ipsos. La diferencia residual con Ipsos puede explicarse porque aún quedan actas rurales pendientes en Cajamarca (77.4 % contado), Piura (70.8 %), Loreto (76.6 %) y otros departamentos donde Sánchez domina.

3. Nota sobre el voto en el extranjero. Con el 68.895 % de mesas del exterior pendientes y una participación observada del 31.6 %, se proyectan ~185,000 votos adicionales. López Aliaga concentra el 33.4 % de ese voto, lo que le sumaría hasta 0.42 pp — insuficiente para cerrar el margen de ~3.3 pp que lo separa de Sánchez.

4. Aliaga converge con Ipsos. El modelo proyecta 11.36 %, prácticamente idéntico al 11.3 % de Ipsos, confirmando que su sobreestimación inicial en el escrutinio parcial era efecto del sesgo urbano.

5. La estructura del voto pendiente favorece a Sánchez como principal candidato al segundo lugar. Las estimaciones sugieren una ventaja consistente, bajo los supuestos del modelo entre Sánchez (13.92 % - 14.66 %) y Aliaga (11.13 % - 11.42 %), con una diferencia aproximada de 3 puntos. Datum sigue siendo el outlier, con Sánchez en 9.4 %, diferencia atribuible a su menor cobertura de mesas rurales.

6. Los 29 candidatos restantes no muestran evidencia estadística de competitividad para la segunda vuelta bajo el escenario modelado. Ninguno supera el 3.5 % del total de votos válidos al 86 % de actas.

7. Alcance interpretativo del modelo. Este modelo no busca predecir el resultado final, sino corregir el sesgo estructural del escrutinio parcial. En ese marco, los resultados deben interpretarse como evidencia direccional sobre el comportamiento del voto pendiente, no como una predicción determinística de clasificación. —

6 Limitaciones del modelo

  • Naturaleza del modelo. El enfoque utilizado corresponde a una estimación frecuentista basada en regresión ponderada (WLS) y simulación (bootstrap), por lo que no constituye un modelo bayesiano formal en sentido estricto. En consecuencia, los resultados deben interpretarse como estimaciones bajo un marco frecuentista y no como inferencias posteriores bayesianas.
  • Hipótesis de orden de llegada de actas. Se asume que las actas se incorporan al escrutinio en un orden predominantemente urbano a rural. En la práctica, este patrón puede verse afectado por factores logísticos, operativos o contingencias específicas, lo que introduciría desviaciones respecto al esquema modelado.
  • Supuesto de linealidad en la relación voto–urbanización. El modelo asume una relación lineal entre el porcentaje de voto de cada candidato y el nivel de urbanización departamental. Esta simplificación puede omitir heterogeneidad relevante asociada a factores geográficos, socioeconómicos o políticos no modelados explícitamente.
  • Tamaño y estructura de la muestra para inferencia. Los intervalos de confianza se estiman mediante bootstrap no paramétrico sobre 25 unidades (departamentos). Dado el tamaño reducido de la muestra y la posible dependencia estructural entre unidades territoriales, estos intervalos deben interpretarse como aproximaciones y no como medidas de precisión estricta.
  • Datos censales de 2017. La distribución urbano/rural utilizada proviene del Censo Nacional 2017, por lo que podrían existir cambios estructurales en la composición territorial no capturados en el modelo.
  • Estabilidad del voto de candidatos restantes. Se asume que la participación conjunta de los 29 candidatos fuera del top 7 se mantiene proporcional a lo observado en el corte del 86 % de actas. Cambios no homogéneos en este grupo podrían alterar marginalmente las proyecciones relativas.
  • Voto exterior. Con solo 2,516 votos pendientes al 31.1 % de actas del exterior escrutadas, su impacto en la proyección final es marginal.