🥇 Recetario abierto, un concurso predictivo

elecciones
pronósticos
encuestas

Una invitación a más cocineros a preparar platos abiertos y transparentes. Con premio incluído.

Autor/a
Afiliación

Recetas Electorales

Análisis independiente

Fecha de publicación

8 de marzo de 2022

Fecha de última modificación

7 de agosto de 2022

“As powerful as single models can be, a collection of models accomplishes even more.”
Scott E. Page

Más recetas, más cocineros

Todos tenemos un modelo en la cabeza de lo que pasa durante unas elecciones –una representación de lo que vemos, de lo que creemos que ocurre y lo que creemos que ocurrirá.

Algunos modelos vienen en forma de especulaciones redactadas en columnas de opinión. Otros vienen de combinar chismes y la información de pasillos, reales o virtuales, sobre las campañas y sus candidatos. Así no sea una #recetaselectorales preparada con datos y modelos estadísticos, hay modelos electorales por todas partes.

Esta receta es una invitación abierta a hacer parte de un recetario electoral más completo, diverso y transparente. La idea es combinar múltiples perspectivas con el ánimo de que corrijan mútuamente sus limitaciones, y así entender mejor la carrera electoral. Es una forma de preparar más y mejores recetas electorales, involucrar más cocineros, y que cada receta se cocine de forma clara, transparente y evaluable. Sin salsas secretas.

Las mejores recetas se llevan un premio. Como es más difícil pronosticar la primera vuelta, el premio es mayor. Las recetas que se vayan recibiendo serán publicadas en una tabla en esta página.

TipPremios:

🥇 Ganador 1era vuelta: La Silla Vacia. Un bono de USD 50 de Amazon

🥇 Ganador 2da vuelta: @PolicitaConDato. Un bono de USD 40 de Amazon

🏆 Oro, plata y bronce electoral

El podio de recetas abiertas quedó así:

Ver código
library(tidyverse)
library(kableExtra)
library(RColorBrewer)

# Evaluacion Cafe ####
readr::read_csv("sancocho_resultados.csv") %>%
  dplyr::select(nombres, plato,pronostico) %>%
  tidyr::pivot_wider(names_from = "plato", values_from = "pronostico") %>%
  tidyr::pivot_longer(cols = c("Encuestas","Simple 2022","Mixto 2022","Ajiaco","@PoliticaConDato","@ColombiaRisk","@JorgeGalindo El Pais","La Silla Vacia","@calc_electoral"), names_to = "plato",values_to = "pronostico") %>%
  # Evaluacion
  dplyr::mutate(evaluacion = abs(Resultado  - pronostico)) %>%
  dplyr::group_by(plato) %>% 
  dplyr::summarize(score = sum(evaluacion)) %>%
  dplyr::arrange(score) %>%
  kable("html", 
        digits=1,
        caption = "Evaluacion de pronósticos para la primera vuelta de 2022:",
        col.names = c("Fuente",
                      "Score Pronóstico")) %>% 
  kable_styling(full_width = F) %>% 
  row_spec(0,bold=TRUE, background = "#FF4900", color = "white") %>%
  # Gold
  row_spec(1,bold=TRUE, italic = TRUE, background="#EEC900",color = "black") %>%
  # Silver
  row_spec(2,bold=TRUE, italic = TRUE, background="#B3B3B3",color = "black") %>%
  # Bronce
  row_spec(3,bold=TRUE, italic = TRUE, background="#CD651B", color = "black") %>%
  footnote(general = c("Score: Distancia absoluta promedio",
                      "Fuente: www.recetas-electorales.com"))
Evaluacion de pronósticos para la primera vuelta de 2022:
Fuente Score Pronóstico
Encuestas 10.0
La Silla Vacia 10.9
@calc_electoral 11.6
@JorgeGalindo El Pais 15.1
@PoliticaConDato 20.0
Ajiaco 21.9
@ColombiaRisk 28.0
Mixto 2022 28.1
Simple 2022 29.3
Note:
Score: Distancia absoluta promedio
Fuente: www.recetas-electorales.com

Recetas abiertas: Evaluación usando distancias absolutas 1era vuelta

Ver código
library(tidyverse)
library(kableExtra)
library(RColorBrewer)

# Encuestas 2022 ####
encuestas_ulr_2022 <- "https://raw.githubusercontent.com/nelsonamayad/Elecciones-presidenciales-2022/main/Encuestas%202022/encuestas_2022.csv"
encuestas_2022 <- readr::read_csv(encuestas_ulr_2022)

# 0. Resultado 2da vuelta ####
resultado_2da_vuelta_2022 <- tribble(~pronostico,~nombres,
                     50.44,"Gustavo Petro",
                     47.31,"Rodolfo Hernandez") %>%
  dplyr::mutate(plato = "Resultado")

# 1. Base: promedio de las encuestas ####
encuestas_2da_vuelta_2022 <- encuestas_2022 %>%
  # Filter despues de consultas 
  dplyr::filter(fecha >= lubridate::as_date("2022-05-29")) %>%
  # Seleccionar candidatos que encabezan las encuestas
  dplyr::select(n,fecha,contains(c("petro","hernandez")),blanco,otros) %>%
  # Pivotear los datos
  tidyr::pivot_longer(cols = c(contains("_"),"blanco","otros"),
                      names_to = "candidato", values_to = "int_voto") %>%
  # Promedios
  dplyr::group_by(candidato) %>%
  dplyr::summarise(pronostico = mean(int_voto,na.rm=TRUE),
                   high = max(int_voto,na.rm=TRUE),
                   low = min(int_voto,na.rm=TRUE)) %>%
  dplyr::mutate(plato= paste0("Encuestas"),
                nombres = case_when(candidato=="rodolfo_hernandez" ~ "Rodolfo Hernandez",
                                    candidato=="gustavo_petro" ~ "Gustavo Petro",
                                    candidato=="blanco" ~ "Voto en blanco",
                                    candidato=="otros" ~ "Otros candidatos",
                                    )
                ) 

# 4. El País ####
elpais_2da_2022 <- readr::read_csv("https://raw.githubusercontent.com/JorgeGalindo/co-elect-2022/main/promedio_evol_2av.csv") %>% 
  dplyr::slice_tail(n=1) %>%
  dplyr::select(gustavo_petro, rodolfo_hernandez) %>%
  tidyr::pivot_longer(cols = everything(),names_to = "candidato",values_to = "pronostico") %>%
  dplyr::mutate(plato= "@JorgeGalindo El Pais",
                nombres = case_when(candidato=="rodolfo_hernandez" ~ "Rodolfo Hernandez",
                                    candidato=="gustavo_petro" ~ "Gustavo Petro"
                                    )
                ) 
  
# 5. La Silla Vacia ####
lsv_2022_2da <- tribble(~pronostico,~nombres,
                     47.2,"Gustavo Petro",
                     46.5,"Rodolfo Hernandez",
                     4,"Voto en blanco") %>%
  dplyr::mutate(plato = "La Silla Vacia")

# 6. PoliticaConDato ####
politicacondato_2da_2022 <- tribble(~pronostico,~nombres,~high,~low,
                     48.3,"Gustavo Petro",54.1,44.8,
                     47.3,"Rodolfo Hernandez",50.7,41.4) %>%
  dplyr::mutate(plato = "@PoliticaConDato")

# 8. Calculo Electoral ####
calculo_electoral_2da_2022 <- tribble(~nombres,~pronostico,~low,~high,
                     "Gustavo Petro",48,NA,NA,
                     "Rodolfo Hernandez",47.3,NA,NA
                     ) %>%
  dplyr::mutate(plato = "@calc_electoral")
  
# 9 Sergio Calvo
sergio_calvo_2da_2022 <-  tribble(~nombres,~pronostico,~low,~high,
                     "Gustavo Petro",48.19,50.83,44.36,
                     "Rodolfo Hernandez",47.69,53.98,40.24
                     ) %>%
  dplyr::mutate(plato = "@Scalvo25")


# Preparar cafe 2da vuelta ####
concurso2022_2da_vuelta <- dplyr::bind_rows(
                             resultado_2da_vuelta_2022,
                             encuestas_2da_vuelta_2022,
                             elpais_2da_2022,
                             lsv_2022_2da,
                             politicacondato_2da_2022,
                             sergio_calvo_2da_2022,
                             calculo_electoral_2da_2022
                             ) %>%
  dplyr::select(plato,nombres,pronostico,high,low) %>%
  dplyr::mutate(nombres = factor(nombres, levels=c("Gustavo Petro","Rodolfo Hernandez")),
                plato = factor(plato,levels = c("Resultado","@JorgeGalindo El Pais","La Silla Vacia","@PoliticaConDato","@calc_electoral","@Scalvo25","Encuestas"))) 

# Concurso 2022 ####
concurso2022_2da_vuelta %>%
  dplyr::filter(!is.na(nombres)) %>%
  dplyr::select(nombres, plato,pronostico) %>%
  tidyr::pivot_wider(names_from = "plato", values_from = "pronostico") %>%
  tidyr::pivot_longer(cols = c("@JorgeGalindo El Pais","La Silla Vacia","@PoliticaConDato","@calc_electoral","@Scalvo25","Encuestas"), names_to = "plato",values_to = "pronostico") %>%
  # Evaluacion
  dplyr::mutate(evaluacion = abs(Resultado  - pronostico)) %>%
  dplyr::group_by(plato) %>% 
  dplyr::summarize(score = sum(evaluacion)) %>%
  dplyr::arrange(score) %>%
  kable("html", 
        digits=1,
        caption = "Evaluacion de pronósticos para la segunda vuelta de 2022:",
        col.names = c("Fuente",
                      "Score Pronóstico")) %>% 
  kable_styling(full_width = F) %>% 
  row_spec(0,bold=TRUE, background = "#FF4900", color = "white") %>%
  # Gold
  row_spec(1,bold=TRUE, italic = TRUE, background="#EEC900",color = "black") %>%
  # Silver
  row_spec(2,bold=TRUE, italic = TRUE, background="#B3B3B3",color = "black") %>%
  # Bronce
  row_spec(3,bold=TRUE, italic = TRUE, background="#CD651B", color = "black") %>%
  footnote(general = c("Score: Distancia absoluta promedio",
                      "Fuente: www.recetas-electorales.com"))
Evaluacion de pronósticos para la segunda vuelta de 2022:
Fuente Score Pronóstico
@PoliticaConDato 2.2
@calc_electoral 2.5
@Scalvo25 2.6
@JorgeGalindo El Pais 3.6
La Silla Vacia 4.0
Encuestas 6.2
Note:
Score: Distancia absoluta promedio
Fuente: www.recetas-electorales.com

Recetas abiertas: Evaluación usando distancias absolutas 2da vuelta


¿Qué tengo que hacer para participar?

Para participar solo hay que enviar una receta a recetas.electorales@gmail.com antes del 22 de Mayo de 2022 para la primera vuelta y antes del 18 de Junio de 2022 para la segunda. Recetas recibidas después cada jornada electoral no cuentan, son descalificadas.

Como las recetas electorales, cada plato debe tener 4 componentes mínimos:

  1. 👨‍🍳 Cocinero y Nombre de la receta: Identidad del que preparó el plato, que puede ser personal o institucional, un nombre para el plato y autorización para publicar en las Recetas Electorales los Ingredientes, Cocina y Plato.
  2. 🍚 Ingredientes - Datos: Todos los datos que usa el modelo deben estar referenciados y deben hacerse públicamente disponibles. Lo mejor es que el modelo tenga un repositorio con todos los datos que utiliza, por ejemplo en GitHub. No hay restriciones sobre los datos que se utilicen mientras se puedan verificar y referenciar.
  3. 🍳 Cocina - Cálculos y Modelos: Cualquier cálculo o modelo estadístico debe incluir el código para estimarlo, evaluarlo, y calcular los pronósticos que resulten. Adicionalmente debe incluir cualquier transformación de los datos (limpieza, wrangling, etc.). Todas las técnicas, desde las más sencillas hasta las más complejas, son aceptadas siempre y cuando sean reproducibles. El código debe ser replicable y puede enviarse en múltiples lenguajes de programación (R, Python, Julia, Stan, etc.)
  4. 🍲 Plato - Resultados: Cada modelo debe resultar en un pronóstico numérico de la votación o proporción de votos que cada candidato obtendrá. Se deben hacer pronósticos sobre todos los candidatos, no solo unos cuantos. Los intervalos de confianza/credibilidad son opcionales, según los vea necesarios cada cocinero.

El ganador

La receta ganadora se determinará por la precisión del pronóstico: El ganador será el modelo con la menor suma del valor absoluto para todos los N candidatos, ponderados por igual, determinada así:

\[ Puntaje = \sum_{candidato=i}^{N} \frac{|Votación_{i} - Pronóstico_{i}|}{N} \]

Si se pronostican proporciones, los votos se miden con respecto al total de votos válidos: votos totales menos votos nulos.

Ejemplo: Un promedio simple de las encuestas disponibles

Ingredientes - Datos

Esta receta usa los datos en el repositorio de GitHub, asi que este paso es solo una linea.

Ver código
# Paquetes ####
library(tidyverse)

# URL GitHub ####
ejemplo_url <- "https://raw.githubusercontent.com/nelsonamayad/Elecciones-presidenciales-2022/main/Encuestas%202022/encuestas_2022.csv"

# Acceder datos ####
ejemplo_datos <- readr::read_csv(ejemplo_url)

Cocina (Modelos) y Plato (Resultados):

Para calcular los promedios para cada candidato se usa el siguiente código y el resultado se resume en una tabla. Dado que es un promedio simple, no incluye intervalos, así que se registra No disponible (ND) para cada candidato:

Ver código
library(tidyverse)
library(kableExtra)

ejemplo_datos %>% 
  # Seleccionar candidatos que encabezan las encuestas
  dplyr::select(n,fecha,encuestadora,muestra,contains("_"),merror=margen_error,-tasa_respuesta,-ns_nr,-muestra_int_voto) %>%
  # Pivotear los datos
  tidyr::pivot_longer(cols = contains("_"),
                      names_to = "candidato", values_to = "int_voto") %>% 
  # Crear algunas variables
  dplyr::mutate(nombres = case_when(candidato=="alejandro_gaviria" ~ "Alejandro Gaviria",
                                    candidato=="sergio_fajardo" ~ "Sergio Fajardo",
                                    candidato=="juan_m_galan" ~ "Juan Manuel Galan",
                                    candidato=="ingrid_betancourt" ~ "Ingrid Betancourt",
                                    candidato=="alex_char" ~ "Alex Char",
                                    candidato=="david_barguil" ~ "David Barguil",
                                    candidato=="enrique_penalosa" ~ "Enrique Peñalosa",
                                    candidato=="federico_gutierrez" ~ "Federico Gutierrez",
                                    candidato=="oscar_i_zuluaga" ~ "Oscar I. Zuluaga",
                                    candidato=="rodolfo_hernandez" ~ "Rodolfo Hernandez",
                                    candidato=="gustavo_petro" ~ "Gustavo Petro") %>%
                  factor()) %>%
  dplyr::group_by(nombres) %>% 
  dplyr::summarise(pronostico=mean(int_voto,na.rm=TRUE)) %>%
  dplyr::mutate(intervalo = "ND") %>%
  dplyr::arrange(desc(pronostico)) %>%
  kable("html", 
        digits=1,
        caption = "Pronostico: % votos por candidato (Basado en encuestas N=3)",
        col.names = c("Candidato",
                      "Pronostico",
                      "Intevalo")) %>% 
  kable_styling(full_width = F) %>% 
  row_spec(0,bold=TRUE, background = "#FF4900", color = "white") %>% 
  footnote(number = c("Cocinero: Recetas Electorales",
                      "Fecha pronóstico: 2022-14-03",
                      "Twitter: @recetaelectoral"))
Pronostico: % votos por candidato (Basado en encuestas N=3)
Candidato Pronostico Intevalo
Gustavo Petro 38.5 ND
Federico Gutierrez 22.2 ND
Rodolfo Hernandez 22.1 ND
Sergio Fajardo 8.0 ND
Alex Char 6.9 ND
Oscar I. Zuluaga 3.8 ND
Juan Manuel Galan 3.5 ND
Alejandro Gaviria 2.3 ND
David Barguil 1.8 ND
Ingrid Betancourt 1.7 ND
Enrique Peñalosa 1.4 ND
1 Cocinero: Recetas Electorales
2 Fecha pronóstico: 2022-14-03
3 Twitter: @recetaelectoral

Evaluación (Hipotética)

Supongamos que se disuelven todas las consultas y se presentan todos los candidatos el 29 de mayo. Ese día se evalúan los resultados del pronóstico así:

Ver código
library(tidyverse)

ejemplo_datos %>% 
  dplyr::select(n,fecha,encuestadora,muestra,contains("_"),merror=margen_error,-tasa_respuesta,-ns_nr,-muestra_int_voto) %>%
  tidyr::pivot_longer(cols = contains("_"),
                      names_to = "candidato", values_to = "int_voto") %>% 
  dplyr::mutate(nombres = case_when(candidato=="alejandro_gaviria" ~ "Alejandro Gaviria",
                                    candidato=="sergio_fajardo" ~ "Sergio Fajardo",
                                    candidato=="juan_m_galan" ~ "Juan Manuel Galan",
                                    candidato=="ingrid_betancourt" ~ "Ingrid Betancourt",
                                    candidato=="alex_char" ~ "Alex Char",
                                    candidato=="david_barguil" ~ "David Barguil",
                                    candidato=="enrique_penalosa" ~ "Enrique Peñalosa",
                                    candidato=="federico_gutierrez" ~ "Federico Gutierrez",
                                    candidato=="oscar_i_zuluaga" ~ "Oscar I. Zuluaga",
                                    candidato=="rodolfo_hernandez" ~ "Rodolfo Hernandez",
                                    candidato=="gustavo_petro" ~ "Gustavo Petro") %>%
                  factor()) %>%
  dplyr::group_by(nombres) %>% 
  # Estimacion promedios
  dplyr::summarise(pronostico=mean(int_voto,na.rm=TRUE)) %>%
  # Join resultados hipoteticos
  dplyr::left_join(
    tribble(~nombres,~resultado_hipotetico,
        "Alejandro Gaviria",10,
        "Sergio Fajardo",15,
       "Juan Manuel Galan",6,
       "Ingrid Betancourt",6,
       "Alex Char",3,
       "David Barguil",3,
       "Enrique Peñalosa",2,
       "Federico Gutierrez",20,
       "Oscar I. Zuluaga",5,
       "Rodolfo Hernandez",5,
       "Gustavo Petro",20,
       "Blanco",5),
       by="nombres") %>%
  # Evaluacion individual
  dplyr::mutate(evaluacion = abs(resultado_hipotetico - pronostico),
                n = n()) %>%
  # Puntaje
  dplyr::mutate(puntaje = cumall(evaluacion)/max(n)) %>%
  dplyr::distinct(puntaje) %>%
  kable("html", 
        digits=2,
        caption = "Puntaje final pronostico:") %>% 
  kable_styling(full_width = F) %>% 
  column_spec(1,  bold=T, background = "#D7261E", color = "white") %>%
  footnote(number = c("Cocinero: Recetas Electorales","Twitter: @recetaelectoral","Fecha pronostico: 2022-14-03"))
Puntaje final pronostico:
puntaje
0.09
1 Cocinero: Recetas Electorales
2 Twitter: @recetaelectoral
3 Fecha pronostico: 2022-14-03

Sugerencias para cocineros creativos

Hay muchos aspectos de las elecciones que se pueden analizar a través de recetas basadas en datos y modelos reproducibles.

Algunas ideas sueltas:

  • Dinámicas regionales: ¿Cómo se distribuyen las votaciones de cada candidatos por departamento y municipio?
  • Voto inconforme: ¿Qué dice el voto en blanco sobre la dinámica electoral? ¿Cómo varía el voto en blanco por vuelta y por geografía?
  • Maquinarias: ¿Cómo se puede modelar la influencia de las maquinarias sobre las elecciones?
  • Sofisticaciones estadísticas: Procesos Gaussianos, ML, etc.

Cómo citar

BibTeX
@online{recetas_electorales2022,
  author = {{Recetas Electorales}},
  title = {🥇 Recetario abierto, un concurso predictivo},
  date = {2022-03-08},
  url = {https://www.recetas-electorales.com/elecciones/2022-colombia/2022-03-18-concurso/2022-concurso.html},
  langid = {es}
}
Por favor, cita este trabajo como:
Recetas Electorales. 2022. “🥇 Recetario abierto, un concurso predictivo.” March 8. https://www.recetas-electorales.com/elecciones/2022-colombia/2022-03-18-concurso/2022-concurso.html.