Wave 2 interim analysis: Baltic crisis

What we check

The preregistration gives two expectations:

  • People agree to more personal sacrifices when the attack is larger.
  • People agree to more personal sacrifices when identity questions come before the crisis.

We expect the same pattern for support for government action.

The four groups

The interim master file contains all four combinations. We can therefore show attack size and identity order separately. The table gives group size, mean and 95% confidence interval for each outcome. Sacrifice ranges from 0 to 4. Government action ranges from 0 to 3.

Code
later_baltic <- w2 %>%
  mutate(attack = if_else(TREATSCALE %% 10 == 2, "Large attack", "Small attack"),
         identity = if_else(POSITION_id == 1, "Identity before", "Identity after"),
         sacrifice = rowSums(pick(baltic_sacrifice_1, baltic_sacrifice_2,
                                  baltic_sacrifice_3, baltic_sacrifice_4)),
         action = pmax(baltic_country_response_level_1,
                       2 * baltic_country_response_level_2,
                       3 * baltic_country_response_level_3))
later_cells <- later_baltic %>% group_by(attack, identity) %>%
  summarise(n = n(), sacrifice = mean(sacrifice, na.rm = TRUE),
            action = mean(action, na.rm = TRUE), .groups = "drop")
read_csv("../../outputs/preliminary_wave2/tables/baltic_pooled_cell_means.csv", show_col_types = FALSE) %>%
  mutate(Attack = if_else(attack_large == 1, "Large", "Small"),
         Identity = if_else(identity_before == 1, "Before", "After")) %>%
  transmute(Attack, Identity, Score = outcome, N = n, Mean = estimate, `95% lower` = conf_low, `95% upper` = conf_high) %>%
  kable(digits = 3)
Attack Identity Score N Mean 95% lower 95% upper
Small After Personal sacrifice 554 1.181 1.095 1.266
Small After Government action 554 1.819 1.726 1.913
Small Before Personal sacrifice 546 1.181 1.090 1.272
Small Before Government action 546 1.815 1.720 1.910
Large After Personal sacrifice 542 1.284 1.191 1.377
Large After Government action 542 1.851 1.756 1.945
Large Before Personal sacrifice 546 1.220 1.130 1.309
Large Before Government action 546 1.808 1.713 1.902

For a short direction check, we first calculate each difference within country. We give the other treatment and each country the same weight.

Code
later_differences <- later_baltic %>%
  mutate(country = as.character(as_factor(Country))) %>%
  group_by(country, attack, identity) %>%
  summarise(sacrifice = mean(sacrifice), action = mean(action), .groups = "drop") %>%
  pivot_longer(c(sacrifice, action), names_to = "score", values_to = "mean") %>%
  group_by(country, score) %>%
  summarise(attack_difference = mean(mean[attack == "Large attack"]) - mean(mean[attack == "Small attack"]),
            identity_difference = mean(mean[identity == "Identity before"]) - mean(mean[identity == "Identity after"]),
            .groups = "drop") %>%
  group_by(score) %>% summarise(across(c(attack_difference, identity_difference), mean))
later_differences %>% kable(digits = 3,
  col.names = c("Score", "Large minus small attack", "Identity before minus after"))
Score Large minus small attack Identity before minus after
action 0.010 -0.039
sacrifice 0.072 -0.046

Size and direction of the differences

Green means the sign matches our expectation. The dashed line marks zero. The numbers are the same equal-country differences as in the table. Colour does not show statistical significance.

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

The table pools records. The differences and the graph give each country the same weight. These can show different patterns when country sample sizes differ. Green means only that the sign matches our expectation. The graphs now include 95% confidence intervals. A predicted sign and an interval excluding zero are different checks.

Results by country

Each row shows one of the four groups within a country. The sacrifice score counts selected personal actions (0 to 4). Government action records the strongest response selected, from no action (0) to troops (3).

Code
country_means <- later_baltic %>% group_by(country, attack, identity) %>%
  summarise(n = n(), sacrifice = mean(sacrifice, na.rm = TRUE),
            action = mean(action, na.rm = TRUE), .groups = "drop")
country_means %>%
  kable(digits = 2, col.names = c("Country", "Attack", "Identity questions", "Records", "Mean sacrifice", "Mean government action"))
Country Attack Identity questions Records Mean sacrifice Mean government action
Croatia Large attack Identity after 50 0.82 1.24
Croatia Large attack Identity before 49 0.92 0.90
Croatia Small attack Identity after 49 0.84 1.20
Croatia Small attack Identity before 52 0.85 1.15
France Large attack Identity after 92 1.09 1.74
France Large attack Identity before 88 0.91 1.56
France Small attack Identity after 89 1.02 1.66
France Small attack Identity before 87 0.93 1.71
Germany Large attack Identity after 91 1.32 1.87
Germany Large attack Identity before 90 1.40 1.97
Germany Small attack Identity after 93 1.32 2.05
Germany Small attack Identity before 91 1.20 1.87
Italy Large attack Identity after 75 0.95 1.21
Italy Large attack Identity before 75 0.96 1.21
Italy Small attack Identity after 77 0.77 1.19
Italy Small attack Identity before 74 0.92 1.34
Poland Large attack Identity after 51 2.14 2.61
Poland Large attack Identity before 54 1.30 2.31
Poland Small attack Identity after 57 1.54 2.23
Poland Small attack Identity before 53 1.64 2.40
Spain Large attack Identity after 100 1.13 1.80
Spain Large attack Identity before 101 1.29 1.97
Spain Small attack Identity after 101 1.07 1.76
Spain Small attack Identity before 103 0.93 1.71
Sweden Large attack Identity after 83 1.71 2.49
Sweden Large attack Identity before 89 1.61 2.40
Sweden Small attack Identity after 88 1.64 2.42
Sweden Small attack Identity before 86 1.86 2.44

Personal sacrifice by country

Each dot is a group average. Blue means identity questions came before the crisis. Orange means they came after it. The numbers show the averages. A rising line means more support under the larger attack. At the same attack size, a higher blue dot means more support when identity questions came first.

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

Government action by country

Read this graph in the same way. Higher scores mean support for a stronger government response. The colours identify question order; they do not mark expected or unexpected results.

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

Which actions do people choose?

Code
w2 %>% select(baltic_sacrifice_1:baltic_sacrifice_4,
              baltic_country_response_level_1:baltic_country_response_level_3) %>%
  pivot_longer(everything(), names_to = "item", values_to = "yes") %>%
  group_by(item) %>% summarise(n = sum(!is.na(yes)), percent_yes = 100 * mean(yes, na.rm = TRUE)) %>%
  mutate(item = recode(item, baltic_sacrifice_1 = "Additional tax", baltic_sacrifice_2 = "Civil work",
    baltic_sacrifice_3 = "Host refugees", baltic_sacrifice_4 = "Enlist",
    baltic_country_response_level_1 = "Sanctions", baltic_country_response_level_2 = "Military equipment",
    baltic_country_response_level_3 = "Troops")) %>%
  kable(digits = 1, col.names = c("Action", "Valid answers", "Yes (%)"))
Action Valid answers Yes (%)
Sanctions 2188 56.4
Military equipment 2188 52.8
Troops 2188 37.2
Additional tax 2188 33.7
Civil work 2188 48.7
Host refugees 2188 28.8
Enlist 2188 10.4

Data and limits

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(country) %>% kable(col.names = c("Country", "Records"))
Country Records
Croatia 200
France 356
Germany 365
Italy 301
Poland 215
Spain 405
Sweden 346
Code
w2 %>% count(attack_large, identity_before) %>%
  kable(col.names = c("Large attack (1=yes)", "Identity before (1=yes)", "Records"))
Large attack (1=yes) Identity before (1=yes) Records
0 0 554
0 1 546
1 0 542
1 1 546

The assignment table has all four combinations. This check alone does not prove that randomization worked in every respect. These are simple unweighted direction checks, with 95% confidence intervals and unadjusted two-sided tests. The final registered analysis will use the completed dataset.

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.

Treatment estimates and confidence intervals

The main effects keep the same equal-country comparisons as before. A country-specific OLS model with the attack-by-identity interaction gives exactly the same point estimates. It also lets us calculate uncertainty for those comparisons. The interaction measures how the attack difference changes when identity questions come before the crisis.

Code
read_csv("../../outputs/preliminary_wave2/tables/baltic_equal_country_effects.csv", show_col_types = FALSE) %>%
  select(outcome, sample, term, n, estimate, std_error, conf_low, conf_high, p_value) %>% kable(digits = 3)
outcome sample term n estimate std_error conf_low conf_high p_value
sacrifice Full sample Large minus small attack 2188 0.072 0.045 -0.016 0.159 0.108
sacrifice Full sample Identity before minus after 2188 -0.046 0.045 -0.133 0.041 0.303
sacrifice Full sample Attack × identity interaction 2188 -0.129 0.089 -0.304 0.046 0.148
sacrifice Without Poland Large minus small attack 1973 0.063 0.046 -0.027 0.152 0.168
sacrifice Without Poland Identity before minus after 1973 0.008 0.046 -0.081 0.098 0.854
sacrifice Without Poland Attack × identity interaction 1973 0.006 0.091 -0.173 0.185 0.948
state_response Full sample Large minus small attack 2188 0.010 0.044 -0.077 0.097 0.820
state_response Full sample Identity before minus after 2188 -0.039 0.044 -0.126 0.048 0.380
state_response Full sample Attack × identity interaction 2188 -0.104 0.089 -0.278 0.069 0.239
state_response Without Poland Large minus small attack 1973 -0.013 0.049 -0.108 0.082 0.787
state_response Without Poland Identity before minus after 1973 -0.035 0.049 -0.130 0.060 0.470
state_response Without Poland Attack × identity interaction 1973 -0.045 0.097 -0.235 0.145 0.643

Does Poland drive the interaction?

We repeat the same model without Poland. The remaining six countries receive equal weight. A significant result in one sample and an insignificant result in the other does not, by itself, show a difference. The exported formal contrast tests Poland against the average interaction in the other countries directly.

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

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

Does identity-item order change the placement effect?

This is a new exploratory analysis. Order 1 runs from municipality to world. Order 2 runs from world to municipality. The questionnaire randomizes this order, and both orders are recorded in both placement groups. Order shown after the crisis cannot prime an earlier answer. We distinguish the order effect among those who see identity first from the placement-by-order interaction.

The predicted means average equally over attack size and country. The three-way test asks whether placement-by-order moderation differs with attack size.

Code
read_csv("../../outputs/preliminary_wave2/tables/identity_order_tests.csv", show_col_types = FALSE) %>% kable(digits = 3)
term n estimate std_error conf_low conf_high p_value outcome
Placement × world-first order 2188 0.091 0.089 -0.084 0.266 0.306 sacrifice
World-first minus local-first; placement=0 2188 -0.063 0.063 -0.186 0.059 0.312 sacrifice
World-first minus local-first; placement=1 2188 0.028 0.064 -0.097 0.153 0.660 sacrifice
Attack × placement × scale order 2188 -0.278 0.179 -0.628 0.072 0.119 sacrifice
Placement × world-first order 2188 -0.038 0.089 -0.212 0.136 0.670 state_response
World-first minus local-first; placement=0 2188 0.022 0.063 -0.102 0.146 0.730 state_response
World-first minus local-first; placement=1 2188 -0.016 0.063 -0.139 0.107 0.797 state_response
Attack × placement × scale order 2188 -0.422 0.178 -0.771 -0.073 0.018 state_response
Code
knitr::include_graphics("../../outputs/preliminary_wave2/figures/baltic_identity_order.png")

Response percentages and enlistment among troop supporters

All valid answers to each item form its denominator. The final row uses only people who selected troop deployment and gave a valid enlistment answer. These percentages describe answers; the difference is not a causal effect.

Code
read_csv("../../outputs/preliminary_wave2/tables/baltic_response_proportions.csv", show_col_types = FALSE) %>%
  transmute(Response = label, Yes = yes, Denominator = n, Percent = 100 * estimate,
            `95% lower (%)` = 100 * conf_low, `95% upper (%)` = 100 * conf_high) %>% kable(digits = 1)
Response Yes Denominator Percent 95% lower (%) 95% upper (%)
Sanctions 1235 2188 56.4 54.4 58.5
Military equipment 1156 2188 52.8 50.7 54.9
Troops 813 2188 37.2 35.2 39.2
Additional tax 738 2188 33.7 31.8 35.7
Civil work 1065 2188 48.7 46.6 50.8
Host refugees 631 2188 28.8 27.0 30.8
Enlist 227 2188 10.4 9.2 11.7
Enlist among troop supporters 169 813 20.8 18.1 23.7
Code
knitr::include_graphics("../../outputs/preliminary_wave2/figures/baltic_response_proportions.png")

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

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

Exploratory geographic proximity

The vignette names Latvia, not a particular attacked town. We use distance from a representative point of each matched NUTS2 region to Latvian territory. This is a regional proxy, not a respondent’s exact location or distance to Riga. The existing GISCO name mapping is reused. Unmatched regions and small regional samples are reported in the diagnostics.

The model allows distance moderation to vary between Germany and Poland. Within each country, distance interacts with attack size, identity placement and their combination. Its intervals cluster at NUTS2 because distance is shared within a region. Separate country fits use t intervals with the number of country-specific clusters minus one degrees of freedom. Curves are shown only over each country’s observed 10th to 90th percentile distances. This is exploratory and observational.

Code
read_csv("../../outputs/preliminary_wave2/diagnostics/geography_coverage.csv", show_col_types = FALSE) %>% kable()
country n matched regions
Germany 365 275 38
Poland 215 210 17
Code
knitr::include_graphics("../../outputs/preliminary_wave2/figures/baltic_geographic_moderation.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.