Austrian Covid data exploration
Exploring the latest figures of COVID19 in Austria
The data used in this post can be found at https://www.data.gv.at/covid-19/. After downloading the CSV file called CovidFaelle_Timeline.csv
, we need to do some cleaning of the date column and split off some specific sets - the numbers for Austria, Volarlberg, Tirol and Wien. We also need to format the decimal numbers since the CSV file uses a ',' instead of a '.' as decimal.
get_new_data = False
if get_new_data:
at_data = pd.read_csv("https://covid19-dashboard.ages.at/data/CovidFaelle_Timeline.csv", sep=';')
at_data['Time'] = pd.to_datetime(at_data['Time'], format='%d.%m.%Y %H:%M:%S')
at_data['SiebenTageInzidenzFaelle'] = [float('.'.join(x.split(','))) for x in at_data.SiebenTageInzidenzFaelle]
at_data.to_csv("../data_sets/CovidFaelle_Timeline.csv", index=False)
else:
at_data = pd.read_csv("../data_sets/CovidFaelle_Timeline.csv", sep=',')
at_data['Time'] = pd.to_datetime(at_data['Time'], format='%Y-%m-%d %H:%M:%S')
current_date = at_data.iloc[-1,0]
all_austria = at_data.query("BundeslandID==10").sort_values(by='Time')
string_to_md = f"- Note that the latest date in this data is {current_date}."
display(Markdown(string_to_md))
latest_data = at_data.query(f"Time>='{str((current_date - datetime.timedelta(7)).date())}'")
saturdays_data = at_data.query("Time.dt.dayofweek == 5").copy()
saturdays_data['rate_change']=saturdays_data.groupby(by='Bundesland').SiebenTageInzidenzFaelle.pct_change().replace(np.inf, np.nan).fillna(0)*100
latest_rate_vbg = latest_data.query("Bundesland=='Vorarlberg'").SiebenTageInzidenzFaelle
latest_rate_aus = latest_data.query("Bundesland=='Österreich'").SiebenTageInzidenzFaelle
vbg_change = round(list(latest_rate_vbg)[-1] - list(latest_rate_vbg)[0]) / list(latest_rate_vbg)[0]
aus_change = round(list(latest_rate_aus)[-1] - list(latest_rate_aus)[0]) / list(latest_rate_aus)[0]
week_trend_vbg = f'<span style="color: green;">Down</span> {vbg_change:.1%}' if vbg_change < 0 else f'<span style="color: red;">Up</span> {vbg_change:.1%}'
week_trend_aus = f'<span style="color: green;">Down</span> {aus_change:.1%}' if aus_change < 0 else f'<span style="color: red;">Up</span>{aus_change:.1%}'
vbg_string = f"Weekly trend in **Vorarlberg**: {week_trend_vbg}"
aus_string = f"Weekly trend in **Austria**: {week_trend_aus}"
display(Markdown(vbg_string))
display(Markdown(aus_string))
source = saturdays_data.query("Time >= '2021-01-31'")
alt.Chart(source).mark_circle(
opacity=0.8,
stroke='black',
strokeWidth=1
).encode(
alt.X('yearmonthdate(Time):T', axis=alt.Axis(title='', labelAngle=-45)),
alt.Y('Bundesland:N'),
alt.Size('rate_change:Q',
scale=alt.Scale(range=[0, 500]),
legend=alt.Legend(title='Percentage change')
),
alt.Color('Bundesland:N', legend=None),
tooltip='rate_change'
).properties(
width=600,
height=320,
title='Percentage change of incidence rate from the previous week'
)
First we have the number of cases per 100,000 population across the whole of Austria. After a very sharp rise in cases during the end of October and the middle of November, the number of new cases have fallen due to the second lockdown. At the time of writting, the cases seem to have levelled off a little - though the Austrian government announced a third lockdown lasting a month starting from the 26th of December, in the expectation that cases will continue to rise over the festive period.
alt.Chart(all_austria).mark_bar(
color='red',
opacity=1,
size=1
).encode(
x=alt.X("yearmonthdate(Time):T", axis=alt.Axis(title='Date')),
y=alt.Y("SiebenTageInzidenzFaelle:Q",
axis=alt.Axis(title='Cases per 100k')),
).configure_axis(grid=True).configure_view(strokeWidth=0.1).properties(
title='Number of cases per 100,000 in Austria', width=800
)
bars = alt.Chart(all_austria).mark_bar(
color='red',
opacity=1,
size=2
).encode(
x=alt.X("yearmonthdate(Time):T", axis=alt.Axis(title='Date')),
y=alt.Y("AnzahlFaelle:Q", axis=alt.Axis(title='New cases')),
)
line = alt.Chart(all_austria).mark_line(
color='blue',
opacity=0.75,
size=1.5,
).transform_window(
rolling_mean='mean(AnzahlFaelle)',
frame=[0, 7]
).encode(x='yearmonthdate(Time):T',
y='rolling_mean:Q'
).properties(title='New cases per day with rolling mean', width=800)
alt.layer(bars, line, data=all_austria)
Next we have the 7 day incidence rate for states of Vorarlberg, Tirol and Wien compared to all of Austria.
leg_selection = alt.selection_multi(fields=['Bundesland'], bind='legend')
brush = alt.selection(type='interval', encodings=['x'])
base = alt.Chart(at_data).mark_line().encode(
x=alt.X("yearmonthdate(Time):T", axis=alt.Axis(title='Date')),
y=alt.Y("SiebenTageInzidenzFaelle:Q", axis=alt.Axis(title='Incidence rate')),
tooltip='Bundesland',
color='Bundesland',
opacity=alt.condition(leg_selection, alt.value(2), alt.value(0.1))
).add_selection(leg_selection).properties(width=800)
upper = base.encode(
alt.X('yearmonthdate(Time):T',axis=alt.Axis(title=''),
scale=alt.Scale(domain=brush))
).properties(title='7 day incidence rate for states in Austria')
lower = base.properties(
height=60
).add_selection(brush)
upper & lower
Finally we have the
brush = alt.selection(type='interval', encodings=['x'])
states = at_data['Bundesland'].unique()
states.sort()
selection = alt.selection_single(
name='Select',
fields=['Bundesland'],
init={'Bundesland': 'Vorarlberg'},
bind={'Bundesland': alt.binding_select(options=states)}
)
# scatter plot, modify opacity based on selection
bars = alt.Chart(at_data).mark_bar().add_selection(
selection
).encode(
x=alt.X("yearmonthdate(Time):T", axis=alt.Axis(title='Date')),
y=alt.Y("SiebenTageInzidenzFaelle:Q", axis=alt.Axis(title='Incidence rate')),
tooltip='SiebenTageInzidenzFaelle:Q',
opacity=alt.condition(selection, alt.value(1), alt.value(0))
).properties(title=f'7 day incidence rate of individual states vs rolling mean across Austria', width=800)
line = alt.Chart(all_austria).mark_line(
color='red',
size=2,
).transform_window(
rolling_mean='mean(SiebenTageInzidenzFaelle)',
frame=[0, 7]
).encode(
x='yearmonthdate(Time):T',
y='rolling_mean:Q'
)
base = alt.layer(bars, line)
upper_bars = bars.encode(
alt.X('yearmonthdate(Time):T',axis=alt.Axis(title='Date'),
scale=alt.Scale(domain=brush))
)
upper_line = line.encode(
alt.X('yearmonthdate(Time):T',axis=alt.Axis(title='Date'),
scale=alt.Scale(domain=brush))
)
upper = alt.layer(upper_bars, upper_line)
lower = base.properties(
height=60
).add_selection(brush)
upper & lower
Choose from the above dropdown menu to view the different states.