Wave 2 interim analysis: input and output democracy

What we check

The preregistration asks which kind of democracy people prefer. Good input means good political processes, such as fair elections. Good output means good government results, such as public services.

The second choice offers good political processes and good government results for people like the respondent, but poor processes and results for others. We call this the self-focused option, or the own-group option. The other scenario applies equally to everyone.

We expect fewer people to choose the self-focused option when the other option is the one they preferred in the first choice.

Code
choice_summary <- w2 %>%
  group_by(comparison_with_preferred) %>%
  summarise(n = sum(!is.na(ego_choice)), ego_percent = 100 * mean(ego_choice, na.rm = TRUE), .groups = "drop")
read_csv("../../outputs/preliminary_wave2/tables/input_pooled_choice_proportions.csv", show_col_types = FALSE) %>%
  transmute(Alternative = if_else(comparison_with_preferred == 1, "Initially preferred", "Initially rejected"), N = n,
            `Own-group choice (%)` = 100 * estimate, `95% lower (%)` = 100 * conf_low, `95% upper (%)` = 100 * conf_high) %>% kable(digits = 1)
Alternative N Own-group choice (%) 95% lower (%) 95% upper (%)
Initially rejected 1111 55.4 52.4 58.3
Initially preferred 1077 24.6 22.1 27.3
Code
gap <- with(choice_summary, ego_percent[comparison_with_preferred == 1] - ego_percent[comparison_with_preferred == 0])

The difference is -30.8 percentage points: preferred alternative minus rejected alternative. Its sign is as expected. This is a simple unadjusted comparison. The adjusted comparison below also accounts for country, the first choice and the alternative shown.

Size and direction of the choice difference

We expect a negative difference: fewer self-focused choices when the alternative was preferred. This bar shows the observed difference in percentage points. The adjusted comparison below provides a second check.

Code
knitr::include_graphics("../../outputs/preliminary_wave2/figures/input_choice_differences.png")

How we code the choices

The answer records the scenario number on screen. The scenario texts can swap positions. We use the position variables to identify the text each person chose.

In the first choice, State A has good output and poor input. State B has good input and poor output. In the second choice, the original first text applies equally to everyone. The original second text is self-focused. Text_inptotpt2 = 2 selects State A as the alternative.

The questionnaire and the saved Run 4 screen check support this coding.

Choices by country

Code
read_csv("../../outputs/preliminary_wave2/tables/input_country_summary_intervals.csv", show_col_types = FALSE) %>%
  transmute(Country = country, Outcome = outcome, N = n, Percent = 100 * estimate,
            `95% lower (%)` = 100 * conf_low, `95% upper (%)` = 100 * conf_high) %>% kable(digits = 1)
Country Outcome N Percent 95% lower (%) 95% upper (%)
Croatia Good output 200 63.5 56.6 69.9
Croatia Own-group option 200 40.5 33.9 47.4
France Good output 356 60.7 55.5 65.6
France Own-group option 356 36.5 31.7 41.6
Germany Good output 365 58.6 53.5 63.6
Germany Own-group option 365 43.6 38.6 48.7
Italy Good output 301 63.8 58.2 69.0
Italy Own-group option 301 35.9 30.7 41.4
Poland Good output 215 72.6 66.2 78.1
Poland Own-group option 215 46.0 39.5 52.7
Spain Good output 405 68.4 63.7 72.7
Spain Own-group option 405 42.5 37.7 47.3
Sweden Good output 346 57.8 52.5 62.9
Sweden Own-group option 346 37.9 32.9 43.1
Code
knitr::include_graphics("../../outputs/preliminary_wave2/figures/input_country_choices.png")

In the graph, each dot shows the percentage choosing the own-group option. “Previously preferred” and “Previously rejected” describe the alternative shown alongside it, based on the respondent’s first choice. They do not describe whether the own-group option itself was preferred or rejected.

Comparison after accounting for other variables

This simple linear model accounts for country, the first choice and the universal alternative shown. Its coefficient is in percentage points. We expect a negative sign. The registered final analysis uses logistic regression.

Code
fit <- lm(ego_choice ~ comparison_with_preferred + universal_A + absolute_preference + country, data = w2)
adjusted_difference <- 100 * unname(coef(fit)["comparison_with_preferred"])
tibble(records_used = nobs(fit), difference_pp = adjusted_difference) %>%
  kable(digits = 2, col.names = c("Records used", "Preferred minus rejected (percentage points)"))
Records used Preferred minus rejected (percentage points)
2188 -26.07

Do Wave 1 answers point in the expected direction?

We use Wave 1 answers for the personal characteristics. We match records by country and serial number. These matches still need confirmation from the survey provider. Germany has no matches.

The tables show the number of matches and any differences in age or gender.

Code
link_check %>% kable()
matched gender_mismatch age_mismatch
1823 2 3
Code
panel %>% count(country) %>% kable()
country n
Croatia 200
France 356
Italy 301
Poland 215
Spain 405
Sweden 346

The check finds 2 gender differences and 3 age gaps larger than one year among the possible matches. These pairs are retained for this overview and need review.

Each model uses one predictor and accounts for country. We do not put all predictors in one model. The estimate shows the change in the percentage choosing an option for a one-unit increase in the predictor.

Each model uses records with the answers it needs. The sample size can therefore differ between rows. “Expected” means that the estimate has the predicted sign. It does not mean that we have confirmed the prediction.

Code
input_panel <- panel %>% mutate(
  log_age_w1 = log(Respondent_Age_w1),
  financial_vulnerability_w1 = 6 - fresil_w1,
  pro_immigration_w1 = ((immiforc_w1 - 1) / 3 + (immiecon_w1 - 1) / 3 + (immicullife_w1 - 1) / 10) / 3
)
# Preserve genuine missing/refused transfer responses; only 99 is the registered zero exception.
transfer_vars <- c("pubpayunemp", "pubpaydisab", "pubpayrent", "pubpaymininc")
transfer_w1 <- w1_raw %>% filter(phase == 2) %>%
  transmute(Respondent_Serial, country = as.character(as_factor(Country)),
    vulnerability_transfer_w1 = as.numeric(rowSums(across(all_of(transfer_vars), ~ case_when(
      .x == 1 ~ 1, .x %in% c(2, 99) ~ 0, TRUE ~ NA_real_))) > 0))
input_panel <- input_panel %>%
  left_join(transfer_w1, by = c("country", "Respondent_Serial"))

predictions <- tribble(
  ~outcome, ~predictor, ~expected,
  "absolute_preference", "polint_w1", -1,
  "absolute_preference", "poldisfam_w1", -1,
  "absolute_preference", "ISCEDRecodeKP_w1", -1,
  "absolute_preference", "log_age_w1", 1,
  "absolute_preference", "economic_left_w1", -1,
  "absolute_preference", "cultural_left_w1", -1,
  "absolute_preference", "idworld_w1", -1,
  "absolute_preference", "financial_vulnerability_w1", 1,
  "absolute_preference", "vulnerability_transfer_w1", 1,
  "absolute_preference", "service_use_w1", 1,
  "ego_choice", "soligame_w1", -1,
  "ego_choice", "percfair_w1", -1,
  "ego_choice", "economic_left_w1", -1,
  "ego_choice", "cultural_left_w1", -1,
  "ego_choice", "dsrvident_w1", 1,
  "ego_choice", "pro_immigration_w1", -1
)
# Outcomes are Wave 2; predictors are Wave 1.
results <- predictions %>% group_by(outcome) %>%
  group_modify(~ direction_models(input_panel, .y$outcome, .x$predictor)) %>% ungroup() %>%
  left_join(predictions, by = c("outcome", "predictor")) %>%
  mutate(estimate_pp = 100 * estimate,
         expected_sign = if_else(expected == 1, "Positive", "Negative"),
         direction = if_else(estimate * expected > 0, "Expected", "Opposite or zero"))
read_csv("../../outputs/preliminary_wave2/tables/input_individual_predictor_models.csv", show_col_types = FALSE) %>%
  filter(specification == "baseline") %>%
  transmute(Outcome = outcome, Predictor = label, N = n, `Estimate (pp)` = 100 * estimate,
            `95% lower (pp)` = 100 * conf_low, `95% upper (pp)` = 100 * conf_high) %>% kable(digits = 2)
Outcome Predictor N Estimate (pp) 95% lower (pp) 95% upper (pp)
absolute_preference Political interest 1813 -3.10 -5.79 -0.40
absolute_preference Political discussion 1816 -1.20 -2.47 0.07
absolute_preference Education 1819 -0.54 -4.17 3.09
absolute_preference Age (log scale) 1823 -8.77 -15.14 -2.40
absolute_preference Economic left orientation 1663 -1.50 -4.02 1.01
absolute_preference Cultural left orientation 1750 -0.69 -3.53 2.14
absolute_preference World identification 1823 -1.46 -4.19 1.28
absolute_preference Financial vulnerability 1674 0.73 -0.95 2.40
absolute_preference Benefit receipt 1801 -1.09 -6.60 4.42
absolute_preference Number of services used 1706 -0.75 -3.04 1.53
ego_choice Solidarity-game transfer 1823 -0.12 -0.20 -0.03
ego_choice Perceived fairness 1823 -1.74 -2.72 -0.77
ego_choice Economic left orientation 1663 -3.94 -6.52 -1.36
ego_choice Cultural left orientation 1750 -0.82 -3.71 2.08
ego_choice Priority for people like me 1823 2.16 -0.24 4.55
ego_choice Positive views of immigration 1704 -23.78 -33.78 -13.78

Country expectations and limits

We expect more output choices in Poland, Croatia and East Germany. We expect fewer in Sweden. The country table allows a first look at Poland, Croatia and Sweden. We do not calculate the registered eight-category country contrasts in this simple overview. Germany has no Wave 1 matches, so the models of individual Wave 1 predictors exclude it.

We do not use weights or fill in missing answers. The updated figures and tables include confidence intervals. We leave the full models and the extra Wave 2 predictors for the main analysis.

Data source and assignment check

We use only w2_data/POLITSOLID_W2_Interim_261007.dta, with 2188 records. Collection is still ongoing. We do not read or add either soft-launch file.

Code
w2 %>% count(POSITION_inptotpt1, POSITION_inptotpt2, Text_inptotpt2) %>%
  kable(col.names = c("First screen position", "Second screen position", "Comparison text", "Records"))
First screen position Second screen position Comparison text Records
1 1 1 273
1 1 2 270
1 2 1 269
1 2 2 282
2 1 1 274
2 1 2 272
2 2 1 271
2 2 2 277

All eight combinations occur in this export. Their presence alone does not prove that randomization worked in every respect. We keep the analysis unweighted and do not fill in missing answers ; confidence intervals and unadjusted p-values are reported below. Panel matches still need provider confirmation.

How to read the confidence intervals

The bars show 95% confidence intervals. If an interval crosses zero, the estimate is not statistically distinguishable from zero at the unadjusted two-sided 5% level. A green estimate can still have an interval crossing zero. The colour records the predicted sign, not statistical significance.

The current export has no Wave 2 weights. Regression intervals use HC2 standard errors. Each panel model uses one change score per person. The graphs of proportions use Wilson intervals. The paired country-change graph uses the variation in each person’s change. The histogram shows counts, so it does not need a confidence interval.

All results remain preliminary. Many comparisons are shown, and their p-values are not corrected for multiple testing. These simple baseline models do not implement every part of the final preregistered analysis.

Choice difference: age and gender robustness

The all-respondent experiment models use Wave 2 age and gender. The individual Wave 1 predictor models use Wave 1 demographics and still exclude unmatched German records. The log-age predictor model adds gender only, to avoid entering age twice.

Code
read_csv("../../outputs/preliminary_wave2/tables/input_choice_differences.csv", show_col_types = FALSE) %>%
  transmute(Model = specification, N = n, `Estimate (pp)` = 100 * estimate, `SE (pp)` = 100 * std_error,
            `95% lower (pp)` = 100 * conf_low, `95% upper (pp)` = 100 * conf_high, p_value) %>% kable(digits = 3)
Model N Estimate (pp) SE (pp) 95% lower (pp) 95% upper (pp) p_value
raw 2188 -30.750 1.988 -34.646 -26.855 0
baseline 2188 -26.071 2.056 -30.101 -22.041 0
age_gender 2187 -25.986 2.056 -30.016 -21.956 0
baseline_common 2187 -26.038 2.057 -30.070 -22.005 0
Code
knitr::include_graphics("../../outputs/preliminary_wave2/figures/input_predictors_age_gender.png")

Dependence sensitivity

The primary regression intervals use HC2. An additional CSV repeats uncertainty calculations using observed administrative regions as clusters. These regions are not documented survey sampling units. This sensitivity checks possible within-region dependence without replacing the primary models.

Code
knitr::include_graphics("../../outputs/preliminary_wave2/figures/input_country_summary.png")