2020 excess mortality & voting patterns in CH

Redistributed cantonal deaths

Data

Canton

Expected deaths by age X sex X canton in 2020 from Riou et al..

Contains iterations of diff results

max(exp_deaths_2020_kt$it)
[1] 1000

Example of one iteration

Data summary
Name Piped data
Number of rows 260
Number of columns 6
_______________________
Column type frequency:
character 3
numeric 3
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
canton 0 1 2 2 0 26 0
age_group 0 1 3 5 0 5 0
sex 0 1 4 6 0 2 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
it 0 1 1.00 0.00 1 1.00 1.0 1.00 1 ▁▁▇▁▁
exp_deaths 0 1 216.61 399.69 0 22.75 75.5 217.25 2857 ▇▁▁▁▁
observed2 0 1 254.35 491.21 0 23.00 81.0 247.75 3891 ▇▁▁▁▁

Municipality

Data prepared in 02.Rmd. Collapsing age groups and renaming variables to match cantonal estimates.

w_deaths_2020_year_fin = read_rds("data/BfS-closed/monthly_deaths/w_deaths_2015_2020_year_fin.Rds") %>% 
  filter(year == 2020) %>% select(-year) %>% 
  rename(age_group = age,
         canton = KTNAME) %>% 
  mutate(age_group = if_else(age_group == "40-49", "40-59", age_group),
         age_group = if_else(age_group == "50-59", "40-59", age_group)) %>% 
  group_by(canton, GMDNR, age_group, sex) %>% 
  summarise(observed = sum(observed),
            pop_mid_poi = sum(pop_mid_poi)) %>% 
  ungroup()
Data summary
Name Piped data
Number of rows 21450
Number of columns 6
_______________________
Column type frequency:
character 3
numeric 3
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
canton 0 1 2 2 0 26 0
age_group 0 1 3 5 0 5 0
sex 0 1 4 6 0 2 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
GMDNR 0 1 3289.82 2133.49 1 1067 3296 5411 6810 ▇▃▅▅▇
observed 0 1 3.55 18.99 0 0 1 3 1493 ▇▁▁▁▁
pop_mid_poi 0 1 403.70 1769.38 0 44 123 336 116058 ▇▁▁▁▁

Spatial

kt = read_rds("data/BfS/kt.Rds")
gg = read_rds("data/BfS/gg.Rds")
tg3o = read_rds("data/BfS/tg3o.Rds")
se_alt = read_rds("data/BfS/se_alt.Rds")

Downscale function

@jriou method to downscale cantonal deaths to municipality level.

source("R/downscale_year.R")

Downscale

exp_deaths_2020_year = downscale_year(exp_deaths_2020_kt, w_deaths_2020_year_fin) %>% 
  rename(
    munici_pop = pop_mid_poi,
    munici_observed = observed,
    cant_exp_deaths = exp_deaths,
    cant_observed = observed2) 

Again, result contains iterations of diff results

max(exp_deaths_2020_year$it)
[1] 1000

Example of one iteration

Data summary
Name Piped data
Number of rows 21450
Number of columns 12
_______________________
Column type frequency:
character 3
numeric 9
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
canton 0 1 2 2 0 26 0
age_group 0 1 3 5 0 5 0
sex 0 1 4 6 0 2 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
GMDNR 0 1.00 3289.82 2133.49 1 1067 3296.00 5411.00 6810 ▇▃▅▅▇
munici_observed 0 1.00 3.55 18.99 0 0 1.00 3.00 1493 ▇▁▁▁▁
munici_pop 0 1.00 403.70 1769.38 0 44 123.00 336.00 116058 ▇▁▁▁▁
it 0 1.00 1.00 0.00 1 1 1.00 1.00 1 ▁▁▇▁▁
cant_exp_deaths 0 1.00 404.91 589.00 0 65 182.00 471.00 2857 ▇▁▁▁▁
cant_observed 0 1.00 467.83 712.77 0 62 173.00 547.00 3891 ▇▁▁▁▁
p 9988 0.53 0.02 0.06 0 0 0.01 0.02 1 ▇▁▁▁▁
munici_exp_deaths 0 1.00 2.63 13.31 0 0 0.00 2.00 856 ▇▁▁▁▁
munici_excess 0 1.00 0.93 6.84 -17 0 0.00 1.00 637 ▇▁▁▁▁

Preps

Aggregates

Iterations collapsed for each municipality strata.

exp_deaths_2020_year_agg = exp_deaths_2020_year %>% 
  group_by(canton, GMDNR, age_group, sex) %>% 
  summarise(
    # observed
    munici_observed = first(munici_observed),
    munici_pop = first(munici_pop),
    # modelled x1000
    # expected
    munici_expected_lo = quantile(munici_exp_deaths, 0.025),
    munici_expected_med = quantile(munici_exp_deaths, 0.5),
    munici_expected_up = quantile(munici_exp_deaths, 0.975),
    # excess
    munici_excess_lo = quantile(munici_excess, 0.025),
    munici_excess_med = quantile(munici_excess, 0.5),
    munici_excess_up = quantile(munici_excess, 0.975)
  ) %>% 
  ungroup()

Even simpler aggregation to municipality level, ignoring age & sex strata.

exp_deaths_2020_year_gem = exp_deaths_2020_year_agg %>% 
  group_by(canton, GMDNR) %>% 
  summarise(
    # community level totals
    munici_pop = sum(munici_pop),
    munici_observed = sum(munici_observed),
    munici_expected_med = sum(munici_expected_med),
    munici_excess_med = sum(munici_excess_med)
  ) %>% 
  ungroup() %>% 
  # ratio and per pop
  mutate(munici_excess_rat = munici_excess_med / munici_expected_med,
         munici_excess_pop =  (munici_excess_med / munici_pop) * 1000) 

Special situation arises in this aggregation when calculating a ratio of excess deaths to observed deaths. There are communities where expected number of deaths is zero. That leads to ratio being Inf in cases where excess is > 0 and to NaN where excess is (also) == 0.

munici_expected_med == 0 <lgl> 
# total N=2145 valid N=2145 mean=0.05 sd=0.21

Value |    N | Raw % | Valid % | Cum. %
---------------------------------------
FALSE | 2042 | 95.20 |   95.20 |  95.20
TRUE  |  103 |  4.80 |    4.80 | 100.00
<NA>  |    0 |  0.00 |    <NA> |   <NA>

These communities’ ratios were recoded to NA.

Bring covariates

exp_deaths_2020_year %<>% 
  left_join(read_rds("data/BfS-closed/monthly_deaths/w_deaths_2015_2020_year_fin.Rds") %>% 
              select(GMDNR, GMDNAME, border, 
                     median_ssep3_q, r_urban1, r_urban2, r_lang) %>% 
              distinct())

exp_deaths_2020_year_agg %<>% 
  left_join(read_rds("data/BfS-closed/monthly_deaths/w_deaths_2015_2020_year_fin.Rds") %>% 
              select(GMDNR, GMDNAME, border, 
                     median_ssep3_q, r_urban1, r_urban2, r_lang) %>% 
              distinct())

exp_deaths_2020_year_gem %<>% 
  left_join(read_rds("data/BfS-closed/monthly_deaths/w_deaths_2015_2020_year_fin.Rds") %>% 
              select(GMDNR, GMDNAME, border, 
                     median_ssep3_q, r_urban1, r_urban2, r_lang) %>% 
              distinct())

Bring voting

covid_jun = read_rds("data/voting/covid_jun.Rds") %>% 
  select(GMDNR, jaStimmenInProzent, vote_yes) %>% 
  rename(vote_yes_jun_perc = jaStimmenInProzent,
         vote_yes_jun_cat = vote_yes)

covid_nov = read_rds("data/voting/covid_nov.Rds") %>% 
  select(GMDNR, jaStimmenInProzent, vote_yes) %>% 
  rename(vote_yes_nov_perc = jaStimmenInProzent,
         vote_yes_nov_cat = vote_yes)

Note: there are few small communities with no voting info - these were excluded.

# A tibble: 4 × 2
  canton GMDNAME                    
  <chr>  <chr>                      
1 BE     Meienried                  
2 BE     Hellsau                    
3 BE     Deisswil bei Münchenbuchsee
4 BE     Niedermuhlern