# load packages
library(readxl)
library(dplyr)
library(stringr)
library(purrr)
library(here)
library(tidyverse)
library(lubridate)
library(knitr)
# read data
df_regular <- readRDS(here("data/local_2024.rds"))
df_special <- readRDS(here("data/special_pre2026.rds"))
# filter to fidesz elections and merge with regular election data
df <- df_special %>%
# keep only fidesz results
filter(grepl("FIDESZ", party, ignore.case = T) ) %>%
# keep only last year
filter(date >= today() - years(1)) %>%
# merge with regular election results
left_join(df_regular,
by = c("loc_distr", "party"), suffix = c("", "_2024")) %>%
# drop districts with no fidesz in regular
filter(!is.na(percentage_2024)) %>%
# calculate swing and cumulative trend
mutate(swing = percentage - percentage_2024) %>%
select(-party)
# calculate a conservative trend without incognito candidates
df_trend_cons <- df %>%
filter(incognito == 0) %>%
mutate(trend = cummean(swing))
# calculate a liberal trend with incognito candidates
df_trend_lib <- df %>%
mutate(trend = cummean(swing))
# Jackknife function to estimate mean for each leave-one-out sample
jackknife_mean <- function(df) {
n <- nrow(df)
map_dfr(1:n, function(i) {
temp <- df[-i, ] %>%
mutate(trend = cummean(swing)) %>%
pull(trend) %>%
last()
tibble(left_out = i,trend = temp)
})
}
# calculate jackknife trends for both version
df_jackknife_cons <- jackknife_mean(df_trend_cons)
df_jackknife_lib <- jackknife_mean(df_trend_lib)
# store the SE based on both versions.
# note, here we are inflating the SE based on the SD.
cons_se <- df_jackknife_cons %>% summarise(se = (n() - 1) / sqrt(n()) * sd(trend))
lib_se <- df_jackknife_lib %>% summarise(se = (n() - 1) / sqrt(n()) * sd(trend))
# for plotting store the final estimate for both versions
cons_lab <- df_trend_cons %>%
last() %>% # most recent point per line
transmute(
# timeline_lab,
lab = round(trend, 1), # label text, 1 decimal
y_lab = trend,
# place label slightly to the right of the last x
x_lab = date + days(5)
)
lib_lab <- df_trend_lib %>%
last() %>% # most recent point per line
transmute(
# timeline_lab,
lab = round(trend, 1), # label text, 1 decimal
y_lab = trend,
# place label slightly to the right of the last x
x_lab = date + days(5)
)
Az elmúlt 12 hónap időközi választásai alapján, konzervatív becslés szerint, a Fidesz országos támogatottsága kábé 48.04, egy kevésbé konzervatív becslés szerint pedig 42.44. Mindkét becslés rémesen pontatlan, de talán hasznos ellenpontot szolgálnak a párt támogatottságát vélhetőleg alulbecslő közvéleménykutatási adatokhoz képest.
Próbáljuk megbecsülni a Fidesz országos támogatottságát időközi választási eredményekből.
Előnyök:
Hátrányok:
Vegyük az elmúlt 12 hónap összes időközi választás eredményét a Nemzeti Választási Iroda oldaláról és szűrjük le az összes olyat, ahol indult Fideszes képviselő. Vessük össze ezt a 2024 júniusi önkormányzati választási eredményekről ugyanonnan megszerzett adatokkal. Csűrjük-csavarjuk az adatokat addig amíg ki nem tudjuk számolni minden egyes időközi választásra, hogy hány százalékpontot változott a Fidesz támogatottsága.
Példa: A február 8-i balmazújvárosi időközin, a 7-es körzet fideszes képviselőjelöltje, Nagy Zoltán a szavazatok 47.1%-át szerezte meg. Ugyanebben a körzetben 2024 júniusában a fideszes jelölt 46.0%-ot kapott. Ennek az időközinek a tanulsága tehát az, hogy a Fidesz 1.1%-t erősödött a körzetben.
Az így kapott összes adatot nemes egyszerűséggel átlagoljuk ki. A módszer fő feltételezése, hogy a Fidesz az ország különböző szegleteiben hol erősebb, hol gyengébb, de ha országosan elmozdul valamilyen irányba a támogatottsága (például csökken 5 százalékpontot), akkor az minden választási körzetben kb ugyanolyan 5%-os elmozdulást fog okozni. Ha 85% volt annak előtte, akkor 80%-ra, ha 26% volt akkor 21%-ra stb.1
Ugyan a 2024 júniusi Önkormányzati választások óta 127 időközi választást tartottak, ebből csupán 16 választás informatív. Egy választás informatív, ha kevesebb, mint egy éve tartották, ha mind az időközin, mind a rendes választáson indul az adott polgármesteri vagy egyéni képviselői székért fideszes jelölt.
Érdekes jelenség, hogy az elmúlt évben több olyan időközi választás is volt, ahol ismert helyi fideszesek függetlenként indultak.
Mi lehet ennek a rejtőzködésnek az oka? Egy lehetőség, hogy az erős helyi ellenzékkel szemben, a választási vereségtől tartva nem akartak rossz fényt vetni a pártra. Való igaz, az ilyen rejtőzködő fideszesek átlagosan -14.7% pontot rontottak a rendes választási eredményekhez képest.
A millió dolláros kérdés, hogy vajon informatív-e az ő szereplésük a Fidesz országos támogatottságának megítéléséhez? Egyrészről, helyben azért a választók többsége tudja, hogy ki hova tartozik. Ha kihagyjuk őket a számításból azt kockáztatjuk, hogy túl pozitív képet kapunk. Másrészről, az is lehet, hogy egy egyébként is kevés embert megmozgató időközi választáson a kormánypárti jelöltek rejtőzködése jó alibit ad a kormánypárt támogatóinak rejtőzködéséhez is, pár százalékkal kevesebben mennek el, holott nem változott a pártpreferenciájuk. Ha ez így van, akkor azáltal, hogy belevesszük őket a számításba alulbecsüljük a Fidesz támogatottságát. Innentől az olvasó vérmérsékletére bízzuk, hogy ezt, vagy azt a becslést hiszi el inkább.
df %>% kable(digits = 1, caption = "A releváns időközi választások")
| loc_distr | date | name | percentage | incognito | name_2024 | percentage_2024 | swing |
|---|---|---|---|---|---|---|---|
| Orosháza 1 | 2025-03-23 | Sándor Zoltánné | 23.5 | 1 | Sándor Zoltánné | 32.4 | -8.9 |
| Mosonmagyaróvár 2 | 2025-04-06 | Nagy András | 19.5 | 0 | Ondré Péter | 36.0 | -16.5 |
| Tiszafüred 2 | 2025-04-06 | Takács Sándorné | 92.0 | 0 | Schöckné Kollár Erzsébet | 52.2 | 39.8 |
| Tiszakécske 2 | 2025-04-06 | Dr. Babák Ferenc | 73.9 | 0 | Petrik András | 75.5 | -1.6 |
| Fót 7 | 2025-04-27 | Márkusné Gonda Zsuzsanna | 11.0 | 1 | Balázsik-Szeder Csaba Attila | 26.8 | -15.8 |
| Hajdúhadház 2 | 2025-05-18 | Batta-Lakatos Judit | 29.4 | 0 | Oroszné Hadházi Zsuzsánna | 27.8 | 1.6 |
| Barcs 2 | 2025-05-25 | Losteiner István | 30.7 | 0 | Récsán Gábor | 48.0 | -17.3 |
| Gárdony 1 | 2025-07-13 | Császár Attila | 26.2 | 1 | Dr. Heresznyei Gabriella | 33.7 | -7.4 |
| Gárdony 4 | 2025-07-13 | Muray Rita | 20.1 | 1 | Czéczei János | 43.5 | -23.3 |
| Budapest VIII. kerület 9 | 2025-09-21 | Kozma Lajos | 52.3 | 0 | Kecskeméti László | 51.4 | 0.9 |
| Gyömrő 6 | 2025-09-28 | Novák Csaba Péter | 36.3 | 0 | Novák Csaba Péter | 15.9 | 20.4 |
| Budapest VIII. kerület 8 | 2025-11-09 | Dr. Pálovics Emese Csilla | 38.3 | 0 | Kaiser Edvin | 45.1 | -6.8 |
| Tolnanémedi Polg | 2025-12-07 | Vigh László | 24.6 | 1 | Vigh László | 42.4 | -17.8 |
| Nagykőrös 8 | 2025-12-14 | Zatykóné Kispál Andrea | 52.4 | 0 | Nagy Balázs | 58.6 | -6.2 |
| Balmazújváros 7 | 2026-02-08 | Nagy Zoltán | 47.1 | 0 | Nagy Zoltán | 46.0 | 1.1 |
| Kazincbarcika 7 | 2026-03-08 | Kaló Attila | 43.2 | 0 | Kaló Attila | 23.4 | 19.8 |
Mint látható az eredményt nagyban befolyásolja, hogy mit gondolunk a rejtőzködő jelöltekről. Ha okosabbnak találjuk ignorálni őket, akkor a Fidesz támogatottsága 3.2% pontot változott az elmúlt évben, tehát most kábé 48.04% körül lehet. Ha azt gondoljuk, hogy érdemes belevenni őket a számításba, akkor a Fidesz támogatottsága -2.4% pontot változott az elmúlt évben, tehát most kábé 42.44% körül lehet.
Mindkét becslésnek nagy a bizonytalansága. Ha elengedjük a tudományos sztendereket, és megelégszünk egy 80%os megbízhatósággal (ami még véletlenül sem azt jelenti, hogy 80% az esélye, hogy a sávon belül van a valós érték), akkor a konzervatív becslés hibahatára +/-6.6, míg a kevésbé konzervatívé +/-5.4%pont.
ggplot(df_trend_lib, aes(x = date)) +
geom_hline(aes(yintercept = 0), color = "gray") +
geom_point(aes(y = swing, alpha = incognito)) +
geom_line(aes(y = trend), linetype = "dashed", color = "royalblue")+
geom_line(data = df_trend_cons,
aes(y = trend))+
geom_text(
data = cons_lab,
aes(x = x_lab, y = y_lab, label = lab),
hjust = 0, size = 3, show.legend = FALSE
) +
geom_text(
data = lib_lab,
aes(x = x_lab, y = y_lab, label = lab),
color = "royalblue",
hjust = 0, size = 3, show.legend = FALSE
) +
ylab("%pont változás (Időközi - Rendes)") + xlab("") +
labs(title = "A Fidesz becsült támogatottsága az időközi választások fényében",
caption = "Mindegyik pont egy-egy időközi választási eredmény.
A trendvonal kumulatív átlagot számol rejtőzködők nélkül (fekete) vagy rejtőzködőkkel (kék szaggatott)") +
scale_alpha(range = c(1, .3), guide = NULL) +
scale_x_date(expand = expansion(mult = c(.01, .06)), # room on the right
date_breaks = "3 months") +
theme_bw() +
theme(legend.position = "bottom")
ggsave(here(paste0("figures/idokozik_", today(), ".jpg")))
Tegyük fel, hogy izgatottan olvastuk a HVG-ben, hogy “már 20% a Tisza előnye”, de aztán eszünkbe jut a Vox Populi blog tanácsa, miszerint érdemes a választani tudók és a biztos szavazók átlagát vennünk, a mintavételből származó standard hibát pedig megdupláznunk. Így azt kell gondolnunk, hogy a Fidesz támogatottsága 36.5%, és standard hiba pedig 6% körül. Ez azt jelenti, hogy 80%-os megbízhatósággal 28.82 és 44.18% pont körül becsüljük a Fidesz támogatottságát.
Namármost, Bayes Tisztelendő híres tételét alkalmazva az időközi választásokon alapuló becslésekkel frissíthetjük várakozásainkat, és az alábbi eredményeket kapjuk.
# Bayesian updating for a Normal prior + Normal likelihood (known SEs)
# prior: theta ~ Normal(mu0, se0)
# data: ybar ~ Normal(theta, se_y)
# returns posterior for theta: Normal(mu_post, se_post)
bayes_update_normal <- function(prior_mean, prior_se, data_mean, data_se) {
stopifnot(is.numeric(prior_mean), is.numeric(prior_se),
is.numeric(data_mean), is.numeric(data_se),
length(prior_mean) == 1, length(prior_se) == 1,
length(data_mean) == 1, length(data_se) == 1,
prior_se > 0, data_se > 0)
w0 <- 1 / (prior_se^2) # prior precision
w1 <- 1 / (data_se^2) # data precision
post_var <- 1 / (w0 + w1)
post_mean <- (w0 * prior_mean + w1 * data_mean) * post_var
post_se <- sqrt(post_var)
return(
paste0(round(post_mean,1), " (", round(post_mean - 1.96*post_se,1), "; ", round(post_mean + 1.96*post_se,1), ")")
)
}
Eszerint érdemes várakozásainkat legalább pár százalékponttal felfelé igazítani, de nem győzöm eleget hangoztatni, hogy tartsuk észben, hogy becsléseink felettébb pontatlanok.
Próbáljuk meg utólag megbecsülni (anglicista neologizmussal: retrodiktálni) a 2018-as választásokon a Fidesz támogatottságát az azt megelőző egy év időközi választási eredményeiből! Persze a múltat megjósolni sokkal könnyebb, mint a jövőt, és vigyáznunk kell, hogy ne az eldobott nyíl köré rajzoljuk a céltáblát. De mégis, ha a fentiekkel egyező módszert alkalmazva hozzávetőleg pontos eredményt kapunk, óvatosan növelhetjük bizalmunkat a módszer hasznosságában.
Mit kell eltalálnia az adatoknak? A Fidesz 2018-ban a belföldi országos listás szavazatok 47.4%-át szerezte meg tehát, a 2014-es 43.6%-os eredményéhez képest 3.8%-ot erősödött.2
Miért ’18-ra készítjük ezt a becslést? Mert 2022-ben a Covid miatt nem voltak időközik a választás előtt, és mert a 2014-es és ’10-es választásokat megelőző időközik nincsenek fenn az Nemzeti Választási Iroda honlapján géppel olvasható formában.
# read data
df_regular14 <- readRDS(here("data/local_2014.rds"))
df_special18 <- readRDS(here("data/special_pre2018.rds"))
# filter to fidesz elections and merge with regular election data
df18 <- df_special18 %>%
# keep only fidesz results
filter(grepl("FIDESZ", party, ignore.case = T) ) %>%
# merge with regular election results
left_join(df_regular14,
by = c("loc_distr", "party"), suffix = c("", "_2014")) %>%
# drop districts with no fidesz in regular, and also
# Domoszlo which was noncompetitive in the regulat
# (Fidesz benchmark = 100%).
filter(!is.na(percentage_2014) & percentage_2014 != 1) %>%
# calculate swing and cumulative trend
mutate(percentage = percentage * 100,
percentage_2014 = percentage_2014 * 100,
swing = percentage - percentage_2014,
trend = cummean(swing)) %>%
select(-party)
# calculate jackknife trends for both version
df_jackknife18<- jackknife_mean(df18)
se18 <- df_jackknife18 %>% summarise(se = (n() - 1) / sqrt(n()) * sd(trend))
lab18 <- df18 %>%
last() %>% # most recent point per line
transmute(
# timeline_lab,
lab = round(trend, 1), # label text, 1 decimal
y_lab = trend,
# place label slightly to the right of the last x
x_lab = date + days(5)
)
A 2018-as becslést több tényező is nehezíti a 2026-os helyzethez képest:
Mindezek ellenére, mint az alábbi ábra is szemlélteti, meglepően pontos becslést adtak az időközi választások, amik összességében egy 3.6 Fidesz erősödést jósoltak volna, alig -0.2%ponttal eltérve a valós eredménytől.
df18 %>% kable(digits = 1, caption = "A releváns időközi választások 2018 előtt")
| loc_distr | date | candidate | percentage | candidate_2014 | percentage_2014 | swing | trend |
|---|---|---|---|---|---|---|---|
| Budapest VIII. kerület6 | 2017-04-23 | Sántha Péterné | 46.0 | Balogh István | 52.5 | -6.6 | -6.6 |
| Budapest XIV. kerület3 | 2017-04-23 | Dr. Somodi Zoltán József | 25.9 | Szatmáry-Jähl Angela | 33.8 | -7.9 | -7.2 |
| Debrecen6 | 2017-05-07 | Türk László | 58.2 | Danku Attila | 57.7 | 0.5 | -4.7 |
| Kisléta Polg | 2017-05-14 | Esztári Lászlóné | 27.8 | Madácsi Imre | 66.7 | -38.9 | -13.2 |
| Gyula8 | 2017-05-21 | Kiss Szabolcs | 56.2 | Balogh Lajos | 55.6 | 0.7 | -10.4 |
| Tatárszentgyörgy Polg | 2017-06-11 | Szehofner József | 68.3 | Szehofner József | 40.9 | 27.3 | -4.1 |
| Paks Polg | 2017-09-10 | Szabó Péter | 68.3 | Kozmann György | 22.2 | 46.1 | 3.0 |
| Tata3 | 2017-10-15 | Purgel Zoltán | 64.4 | Nágel Balázs | 44.5 | 20.0 | 5.2 |
| Solymár6 | 2017-12-10 | Dalos Attila | 56.8 | Gaal Gergely | 62.0 | -5.1 | 4.0 |
| Hódmezővásárhely Polg | 2018-02-25 | Hegedűs Zoltán | 41.6 | Almási István | 61.0 | -19.4 | 1.7 |
| Kiskunhalas5 | 2018-02-25 | Juhász György | 68.1 | Aradszky László Andrásné | 45.2 | 22.9 | 3.6 |
ggplot(df18, aes(x = date)) +
geom_hline(aes(yintercept = 0), color = "gray") +
geom_point(aes(y = swing)) +
geom_line(aes(y = trend))+
geom_text(
data = lab18,
aes(x = x_lab, y = y_lab, label = lab),
hjust = 0, size = 3, show.legend = FALSE
) +
ylab("%pont változás (Időközi - Rendes)") + xlab("") +
labs(title = "A Fidesz becsült támogatottsága 2018-ban az időközi választások fényében",
caption = "Mindegyik pont egy-egy időközi választási eredmény.
A trendvonal kumulatív átlagot számol.") +
scale_alpha(range = c(1, .3), guide = NULL) +
scale_x_date(expand = expansion(mult = c(.01, .06)), # room on the right
date_breaks = "3 months") +
theme_bw() +
theme(legend.position = "bottom")
Érdemes azonban ezt legalább két okból is erős fenntartásokkal
kezelni.
Köszönjük megtisztelő figyelmét. Kérés, kérdés, kritika esetén keressen bátran a bora@ceu.edu címen.
Szemfüles olvasóinknak feltűnhet, hogy a módszer nem bombabiztos, a plafon és padló környékén szürrealitásokat okozhat. Szerencsére az ilyen esetek elég ritkák ahhoz, hogy figyelmen kívül hagyjuk őket.↩︎
Köszönöm a Választási Földrajz javaslatát, hogy itt a (határontúli) levélszavazatokat ne vegyük figyelembe.↩︎