Compare the excess mortality rates of European countries in 2020 with those of earlier time periods

The data was downloaded from EuroStat website on September 29th

Read cleaned data, calculate excess mortalities and compare them based on Wilcoxon's rank sum test

clear
Tbl = readtable('C:\Users\MSchneider\Documents\CoronaFacts\DataEurostat\demo_r_mwk_ts.xlsx', 'Sheet','DataCleanedV2', 'Range','A1:AM1082');
countryidx = 3:39; % column indizes of the contries
nc = length(countryidx);
alpha = 0.05; % significance level for CIs and hypothesis tests
y = table;
countries = Tbl.Properties.VariableNames(countryidx);
lr = 18; % look 'lr' indizes left and right to the peaks and look for excess mortality
for i = 1:nc
excess_2020 = NaN; % initialisation since some traces might not reach 2020
country = countries{i};
fprintf('Analyzing country "%s" (number %d of %d)\n', country, i, nc)
y = Tbl.(country);
xweeks = Tbl.TIME(~isnan(y));
y = y(~isnan(y));
%x = [1:height(Tbl)]';
x = [1:length(y)]';
cos52 = cos((2*pi/(365.25/7)) * x);
sin52 = sin((2*pi/(365.25/7)) * x);
sin26 = sin((4*pi/(365.25/7)) * x);
cos26 = cos((4*pi/(365.25/7)) * x);
%modelspec = [country, ' ~ 1+ cos52 + sin52 + cos26 + sin26 + index'];
modelspec = [country, ' ~ 1 + cos52 + sin52 + x'];
mytab = [table(y, 'VariableNames',{country}), table(cos52), table(sin52), table(cos26), table(sin26), table(x)];
% Model is quasi-Poisson (dispersion flag is true)
mdl = fitglm(mytab, modelspec, 'Distribution','poisson', 'DispersionFlag', true);
[ypred, y_ci] = predict(mdl,mytab,'Alpha',0.05,'Simultaneous',false);
yci_lower = y_ci(:,1);
yci_upper = y_ci(:,2);
% plot the results
figure('Name', country)
subplot(2,1,1)
hold on
plot(x, y)
plot(x, ypred, 'k')
plot(x, yci_upper, 'm--')
title(country)
ylabel('Weekly death counts')
% Set x-ticks manually
xtickrange = round(linspace(min(x), max(x), 10));
xticks(xtickrange)
xticklabels(xweeks(xtickrange,1)')
xtickangle(45)
hold off
% Detect maxima of the baseline 'ypred' and find find excess
% mortalities
excess_res = y - yci_upper;
[loc, ~]=peakseek(ypred,40,mean(ypred));
idx_low = loc - lr;
idx_hi = loc + lr;
idx_low(idx_low < 1) = 1;
idx_hi(idx_hi > length(ypred)) = length(ypred);
for j=1:numel(loc)
idx = idx_low(j):idx_hi(j);
%plot(x(idx), ypred(idx), 'x')
idxintbl = strfind(Tbl.(country)', y(idx)') + [0:length(y(idx))-1];
yearweekcell = cell2mat(cellfun(@(x) str2double(x(1:4)),...
Tbl.TIME(idxintbl),'un',0));
excess_res_sum = excess_res(idx);
% Plot those which are positive
idxpos = idx(excess_res_sum > 0);
curve1 = yci_upper;
x2 = x;
curve2 = y;
ix = curve2 < curve1;
curve2(ix) = curve1(ix);
%plot(x(idxpos), y(idxpos), 'rv', 'MarkerSize', 3) % highlight excess mort. data points with triangles
% Plot shaded peaks.
subplot(2,1,2)
[ph,msg] = jbfill(x2(:)',curve2(:)', curve1(:)');
ylabel('Weekly death counts')
xtickrange = round(linspace(min(x), max(x), 10));
xticks(xtickrange)
xticklabels(xweeks(xtickrange,1)')
xtickangle(45)
hold off
if yearweekcell(end) == 2020
% Count the positive (excess) residuals
excess_2020 = sum(y(idxpos) - yci_upper(idxpos));
else
excess_earlier(j) = sum(y(idxpos) - yci_upper(idxpos));
end
end
% Values equal to zero are no excess mortality per definitionem
excess_earlier = excess_earlier(excess_earlier > 0);
mdata.(country).Excess2020 = excess_2020;
mdata.(country).ExcessEarlier = excess_earlier;
% Perform Wilcoxon Rank Sum test to compare excess mortality of 2020
% with the excess mortality of previous years
if (length(excess_earlier) > 2 && ~isnan(excess_2020))
[p,h] = signrank(excess_earlier, excess_2020(end),'alpha', alpha,...
'tail', 'left');
% Rem.: Signficantly could also mean the excess mortality in 2020
% is significantly less than in earlier years -> so make a
% one-tailed test
mdata.(country).SignificantlyMoreIn2020 = h;
% make a qqplot if there is enough data from previous years
if length(excess_earlier) > 10
figqqplot = figure;
[mdata.(country).DataNormal, ~, ~] = swtest(excess_earlier, alpha);
qqplot(excess_earlier);
saveas(gcf, [country, '_excessmortality_qqplot.png'])
close(figqqplot)
end
else
mdata.(country).SignificantlyMoreIn2020 = NaN;
end
mdata.(country).Trace = y;
clear excess_earlier excess_2020
end
Analyzing country "Belgium" (number 1 of 37)
Analyzing country "Bulgaria" (number 2 of 37)
Analyzing country "Czechia" (number 3 of 37)
Analyzing country "Denmark" (number 4 of 37)
Analyzing country "Germany" (number 5 of 37)
Analyzing country "Estonia" (number 6 of 37)
Analyzing country "Greece" (number 7 of 37)
Analyzing country "Spain" (number 8 of 37)
Analyzing country "France" (number 9 of 37)
Analyzing country "Croatia" (number 10 of 37)
Analyzing country "Italy" (number 11 of 37)
Analyzing country "Cyprus" (number 12 of 37)
Analyzing country "Latvia" (number 13 of 37)
Analyzing country "Lithuania" (number 14 of 37)
Analyzing country "Luxembourg" (number 15 of 37)
Analyzing country "Hungary" (number 16 of 37)
Analyzing country "Malta" (number 17 of 37)
Analyzing country "Netherlands" (number 18 of 37)
Analyzing country "Austria" (number 19 of 37)
Analyzing country "Poland" (number 20 of 37)
Analyzing country "Portugal" (number 21 of 37)
Analyzing country "Romania" (number 22 of 37)
Analyzing country "Slovenia" (number 23 of 37)
Analyzing country "Slovakia" (number 24 of 37)
Analyzing country "Finland" (number 25 of 37)
Analyzing country "Sweden" (number 26 of 37)
Analyzing country "UnitedKingdom" (number 27 of 37)
Analyzing country "Iceland" (number 28 of 37)
Analyzing country "Liechtenstein" (number 29 of 37)
Analyzing country "Norway" (number 30 of 37)
Analyzing country "Switzerland" (number 31 of 37)
Analyzing country "Montenegro" (number 32 of 37)
Analyzing country "Albania" (number 33 of 37)
Analyzing country "Serbia" (number 34 of 37)
Analyzing country "Andorra" (number 35 of 37)
Analyzing country "Armenia" (number 36 of 37)
Analyzing country "Georgia" (number 37 of 37)

Print the key results to the command line

clc
for ii=1:nc
if isnan(mdata.(countries{ii}).SignificantlyMoreIn2020)
fprintf('The significance of the excess mortality in %s in 2020 could not be determined\n',...
countries{ii})
elseif mdata.(countries{ii}).SignificantlyMoreIn2020
fprintf('There was a significant excess mortality in %s in 2020 compared to previous years\n',...
countries{ii})
else
fprintf('There was no significant excess mortality in %s in 2020 compared to previous years\n',...
countries{ii})
end
end
There was a significant excess mortality in Belgium in 2020 compared to previous years
There was no significant excess mortality in Bulgaria in 2020 compared to previous years
There was no significant excess mortality in Czechia in 2020 compared to previous years
There was no significant excess mortality in Denmark in 2020 compared to previous years
There was no significant excess mortality in Germany in 2020 compared to previous years
The significance of the excess mortality in Estonia in 2020 could not be determined
There was no significant excess mortality in Greece in 2020 compared to previous years
There was a significant excess mortality in Spain in 2020 compared to previous years
There was a significant excess mortality in France in 2020 compared to previous years
There was no significant excess mortality in Croatia in 2020 compared to previous years
There was no significant excess mortality in Italy in 2020 compared to previous years
There was no significant excess mortality in Cyprus in 2020 compared to previous years
The significance of the excess mortality in Latvia in 2020 could not be determined
There was no significant excess mortality in Lithuania in 2020 compared to previous years
There was a significant excess mortality in Luxembourg in 2020 compared to previous years
There was no significant excess mortality in Hungary in 2020 compared to previous years
There was no significant excess mortality in Malta in 2020 compared to previous years
There was a significant excess mortality in Netherlands in 2020 compared to previous years
There was no significant excess mortality in Austria in 2020 compared to previous years
There was no significant excess mortality in Poland in 2020 compared to previous years
There was no significant excess mortality in Portugal in 2020 compared to previous years
The significance of the excess mortality in Romania in 2020 could not be determined
There was no significant excess mortality in Slovenia in 2020 compared to previous years
There was no significant excess mortality in Slovakia in 2020 compared to previous years
There was no significant excess mortality in Finland in 2020 compared to previous years
There was a significant excess mortality in Sweden in 2020 compared to previous years
There was a significant excess mortality in UnitedKingdom in 2020 compared to previous years
There was a significant excess mortality in Iceland in 2020 compared to previous years
There was no significant excess mortality in Liechtenstein in 2020 compared to previous years
There was no significant excess mortality in Norway in 2020 compared to previous years
There was a significant excess mortality in Switzerland in 2020 compared to previous years
There was no significant excess mortality in Montenegro in 2020 compared to previous years
The significance of the excess mortality in Albania in 2020 could not be determined
There was no significant excess mortality in Serbia in 2020 compared to previous years
The significance of the excess mortality in Andorra in 2020 could not be determined
There was no significant excess mortality in Armenia in 2020 compared to previous years
There was no significant excess mortality in Georgia in 2020 compared to previous years
Please note that I used some external MATLAB functions from MATLAB Central File Exchange:
Please also note that I used some of the R-Code from EUROMOMO as sort of template for the analysis here. The corresponding R-package can be downloaded from the EUROMOMO website.