Visualisatie van GGD leeftijds data¶

Data importeren¶

In [1]:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import geopandas as gpd
from datetime import date,datetime,timedelta
from matplotlib.ticker import ScalarFormatter
import numpy as np
from matplotlib.colors import LinearSegmentedColormap, to_rgba_array
In [2]:
ageGroupStats = pd.read_csv( "data/rivm-cases-per-ggd-per-age-group.csv", parse_dates=["Date"])
dateOfStats = ageGroupStats.Date.max()
ageGroupStats = ageGroupStats[ageGroupStats.Date <= (dateOfStats - timedelta(days=3))].copy() # remove last 3 noisy days
print(f"GGD data import: {dateOfStats}")
ageGroupStats
GGD data import: 2023-04-04 00:00:00
Out[2]:
Date GGD_name Age_group Positive_cases Positive_cases_per100k
0 2021-10-04 Dienst Gezondheid & Jeugd ZHZ 0-9 6 12.005
1 2021-10-04 Dienst Gezondheid & Jeugd ZHZ 10-19 11 20.083
2 2021-10-04 Dienst Gezondheid & Jeugd ZHZ 20-29 19 35.519
3 2021-10-04 Dienst Gezondheid & Jeugd ZHZ 30-39 9 16.260
4 2021-10-04 Dienst Gezondheid & Jeugd ZHZ 40-49 10 17.676
... ... ... ... ... ...
141695 2023-04-01 NaN 50-59 0 NaN
141696 2023-04-01 NaN 60-69 0 NaN
141697 2023-04-01 NaN 70-79 0 NaN
141698 2023-04-01 NaN 80-89 0 NaN
141699 2023-04-01 NaN 90+ 0 NaN

141700 rows × 5 columns

In [3]:
map_data = gpd.read_file("https://cartomap.github.io/nl/wgs84/ggdregio_2021.geojson")

Data voorbereiden¶

In [4]:
sum7d_totals = ageGroupStats.copy().groupby(by=["GGD_name", "Age_group"]).rolling(on="Date", window=7).sum().reset_index()
sum7d_totals["growth"] = sum7d_totals.Positive_cases.rolling(window=7).sum().pct_change().replace([np.inf, -np.inf], 0).fillna(0).rolling(window=7).mean() * 100
sum7d_totals
Out[4]:
GGD_name Age_group level_2 Date Positive_cases Positive_cases_per100k growth
0 Dienst Gezondheid & Jeugd ZHZ 0-9 0 2021-10-04 NaN NaN NaN
1 Dienst Gezondheid & Jeugd ZHZ 0-9 260 2021-10-05 NaN NaN NaN
2 Dienst Gezondheid & Jeugd ZHZ 0-9 520 2021-10-06 NaN NaN NaN
3 Dienst Gezondheid & Jeugd ZHZ 0-9 780 2021-10-07 NaN NaN NaN
4 Dienst Gezondheid & Jeugd ZHZ 0-9 1040 2021-10-08 NaN NaN NaN
... ... ... ... ... ... ... ...
136245 Veiligheids- en Gezondheidsregio Gelderland-Mi... 90+ 140649 2023-03-28 8.0 148.672 -7.229367
136246 Veiligheids- en Gezondheidsregio Gelderland-Mi... 90+ 140909 2023-03-29 7.0 130.088 -7.161774
136247 Veiligheids- en Gezondheidsregio Gelderland-Mi... 90+ 141169 2023-03-30 6.0 111.504 -6.990637
136248 Veiligheids- en Gezondheidsregio Gelderland-Mi... 90+ 141429 2023-03-31 4.0 74.336 -7.423013
136249 Veiligheids- en Gezondheidsregio Gelderland-Mi... 90+ 141689 2023-04-01 4.0 74.336 -8.098348

136250 rows × 7 columns

In [5]:
mins = sum7d_totals.groupby(by=["Date", "Age_group"]).min()
maxs = sum7d_totals.groupby(by=["Date", "Age_group"]).max()
medians = sum7d_totals.groupby(by=["Date", "Age_group"]).median()
avg = sum7d_totals.groupby(by=["Date", "Age_group"]).mean()
avg["min"] = mins.growth
avg["max"] = maxs.growth
avg["median"] = medians.growth
avg = avg.reset_index()

avg_absolutes = sum7d_totals.groupby(by=["Date", "Age_group"]).mean()
avg_absolutes["min"] = mins.Positive_cases_per100k
avg_absolutes["max"] = maxs.Positive_cases_per100k
avg_absolutes["median"] = medians.Positive_cases_per100k
avg_absolutes = avg_absolutes.reset_index()

Plots configureren¶

In [6]:
sns.set_context("talk", font_scale=0.9, rc={"lines.linewidth": 3, "font.size":8,"axes.titlesize":24,"axes.labelsize":18})
sns.set_style("whitegrid")
sns.set_theme(style="ticks")
#sns.set_palette(sns.color_palette("colorblind"))
sns.set_palette(sns.color_palette(['#CC6677', '#332288', '#DDCC77', '#117733', '#88CCEE', \
                    '#882255', '#44AA99', '#999933', '#AA4499', '#DDDDDD', \
                    '#000000']))

def discretemap(colormap, hexclrs):
    """
    Produce a colormap from a list of discrete colors without interpolation.
    """
    clrs = to_rgba_array(hexclrs)
    clrs = np.vstack([clrs[0], clrs, clrs[-1]])
    cdict = {}
    for ki, key in enumerate(('red','green','blue')):
        cdict[key] = [ (i/(len(clrs)-2.), clrs[i, ki], clrs[i+1, ki]) for i in range(len(clrs)-1) ]
    return LinearSegmentedColormap(colormap, cdict)

def __rainbow_WhBr():
    """
    Define colormap 'rainbow_WhBr'.
    """
    clrs = ['#E8ECFB', '#DDD8EF', '#D1C1E1', '#C3A8D1', '#B58FC2',
            '#A778B4', '#9B62A7', '#8C4E99', '#6F4C9B', '#6059A9',
            '#5568B8', '#4E79C5', '#4D8AC6', '#4E96BC', '#549EB3',
            '#59A5A9', '#60AB9E', '#69B190', '#77B77D', '#8CBC68',
            '#A6BE54', '#BEBC48', '#D1B541', '#DDAA3C', '#E49C39',
            '#E78C35', '#E67932', '#E4632D', '#DF4828', '#DA2222',
            '#B8221E', '#95211B', '#721E17', '#521A13']
    return LinearSegmentedColormap.from_list("Rainbo_WhBr", clrs)
    #self.cmap.set_bad('#666666')

def __iridescent():
    """
    Define colormap 'iridescent'.
    """
    clrs = ['#FEFBE9', '#FCF7D5', '#F5F3C1', '#EAF0B5', '#DDECBF',
            '#D0E7CA', '#C2E3D2', '#B5DDD8', '#A8D8DC', '#9BD2E1',
            '#8DCBE4', '#81C4E7', '#7BBCE7', '#7EB2E4', '#88A5DD',
            '#9398D2', '#9B8AC4', '#9D7DB2', '#9A709E', '#906388',
            '#805770', '#684957', '#46353A']
    return LinearSegmentedColormap.from_list("iridescent", clrs)
    #self.cmap.set_bad('#999999')

def __YlOrBr():
    """
    Define colormap 'YlOrBr'.
    """
    clrs = ['#FFFFE5', '#FFF7BC', '#FEE391', '#FEC44F', '#FB9A29',
            '#EC7014', '#CC4C02', '#993404', '#662506']
    return LinearSegmentedColormap.from_list('YlOrBr', clrs)
    #self.cmap.set_bad('#888888')

def __BuRd():
    """
    Define colormap 'BuRd'.
    """
    clrs = ['#2166AC', '#4393C3', '#92C5DE', '#D1E5F0', '#F7F7F7',
            '#FDDBC7', '#F4A582', '#D6604D', '#B2182B']
    return LinearSegmentedColormap.from_list('BuRd', clrs)

def __rainbow_discrete(self, lut=None):
    """
    Define colormap 'rainbow_discrete'.
    """
    clrs = ['#E8ECFB', '#D9CCE3', '#D1BBD7', '#CAACCB', '#BA8DB4',
            '#AE76A3', '#AA6F9E', '#994F88', '#882E72', '#1965B0',
            '#437DBF', '#5289C7', '#6195CF', '#7BAFDE', '#4EB265',
            '#90C987', '#CAE0AB', '#F7F056', '#F7CB45', '#F6C141',
            '#F4A736', '#F1932D', '#EE8026', '#E8601C', '#E65518',
            '#DC050C', '#A5170E', '#72190E', '#42150A']
    indexes = [[9], [9, 25], [9, 17, 25], [9, 14, 17, 25], [9, 13, 14, 17,
            25], [9, 13, 14, 16, 17, 25], [8, 9, 13, 14, 16, 17, 25], [8,
            9, 13, 14, 16, 17, 22, 25], [8, 9, 13, 14, 16, 17, 22, 25, 27],
            [8, 9, 13, 14, 16, 17, 20, 23, 25, 27], [8, 9, 11, 13, 14, 16,
            17, 20, 23, 25, 27], [2, 5, 8, 9, 11, 13, 14, 16, 17, 20, 23,
            25], [2, 5, 8, 9, 11, 13, 14, 15, 16, 17, 20, 23, 25], [2, 5,
            8, 9, 11, 13, 14, 15, 16, 17, 19, 21, 23, 25], [2, 5, 8, 9, 11,
            13, 14, 15, 16, 17, 19, 21, 23, 25, 27], [2, 4, 6, 8, 9, 11,
            13, 14, 15, 16, 17, 19, 21, 23, 25, 27], [2, 4, 6, 7, 8, 9, 11,
            13, 14, 15, 16, 17, 19, 21, 23, 25, 27], [2, 4, 6, 7, 8, 9, 11,
            13, 14, 15, 16, 17, 19, 21, 23, 25, 26, 27], [1, 3, 4, 6, 7, 8,
            9, 11, 13, 14, 15, 16, 17, 19, 21, 23, 25, 26, 27], [1, 3, 4,
            6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 19, 21, 23, 25, 26,
            27], [1, 3, 4, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 20,
            22, 24, 25, 26, 27], [1, 3, 4, 6, 7, 8, 9, 10, 12, 13, 14, 15,
            16, 17, 18, 20, 22, 24, 25, 26, 27, 28], [0, 1, 3, 4, 6, 7, 8,
            9, 10, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 25, 26, 27, 28]]
    if lut == None or lut < 1 or lut > 23:
        lut = 22
    self.cmap = discretemap(self.cname, [ clrs[i] for i in indexes[lut-1] ])
    if lut == 23:
        self.cmap.set_bad('#777777')
    else:
        self.cmap.set_bad('#FFFFFF')
In [7]:
def tuftefy(ax):
    """Remove spines and tick position markers to reduce ink."""
    # 
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
    ax.spines["left"].set_visible(False)
    ax.spines["bottom"].set_visible(True)
    ax.spines["bottom"].set_color('grey')

    ax.grid(color="w", alpha=0.5)
    ax.get_yaxis().grid(True)
    ax.get_xaxis().grid(False)

def fancy_titles(t1, t2, ax=None):
  if ax:
    ax.set_title(t1, loc='left', fontsize=18)
    ax.set_title(t2, loc='right', fontsize=13, color='grey')
  else:
    plt.title(t1, loc='left', fontsize=18)
    plt.title(t2, loc='right', fontsize=13, color='grey')

Plots¶

Kaartjes¶

In [8]:
annotated_map = map_data.copy().set_index('statnaam').join(sum7d_totals[sum7d_totals.Date == sum7d_totals.Date.max()].copy().set_index('GGD_name'), how='left')

g = sns.FacetGrid(annotated_map, col="Age_group", col_wrap=4, margin_titles=True, legend_out=True)
def map_plot(data, **kws):
    ax = plt.gca()
    data.plot("Positive_cases_per100k", cmap=__YlOrBr(), ax= ax, vmin=0, vmax=700, edgecolor="#cccccc", legend=True)
    ax.set_axis_off()


g = g.map_dataframe(map_plot)

g.set_titles(col_template = '{col_name}')
g.add_legend(loc='upper right')

g.despine()
plt.tight_layout()
plt.subplots_adjust(hspace=0.1, wspace=0.05, top=0.93)
g.fig.suptitle('Aantal positieve testen afgelopen week per 100.000 inwoners', size=16.0, weight='bold')
g.fig.text(1,0.03, "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d') + " & CBS statistiek", ha="right", fontsize=12, color='grey')
#annotated_map.plot("Positive_cases_per100k", legend=True)
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
Out[8]:
Text(1, 0.03, 'bron: RIVM update 2023-04-04 & CBS statistiek')
In [9]:
annotated_map = map_data.copy().set_index('statnaam').join(sum7d_totals[sum7d_totals.Date == sum7d_totals.Date.max()].copy().set_index('GGD_name'), how='left')

g = sns.FacetGrid(annotated_map, col="Age_group", col_wrap=4, margin_titles=True, legend_out=True)
def map_plot(data, **kws):
    ax = plt.gca()
    data.plot("growth", cmap=__BuRd(), ax= ax, vmin=-10, vmax=10, edgecolor="#cccccc", legend=True)
    ax.set_axis_off()


g = g.map_dataframe(map_plot)

g.set_titles(col_template = '{col_name}')
g.add_legend(loc='upper right')

g.despine()
plt.tight_layout()
plt.subplots_adjust(hspace=0.1, wspace=0.05, top=0.93)
g.fig.suptitle('Groei percentage positieve testen (7d gemiddelde)', size=16.0, weight='bold')
g.fig.text(1,0.03, "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d') + " & CBS statistiek", ha="right", fontsize=12, color='grey')
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
/opt/buildhome/python3.7/lib/python3.7/site-packages/geopandas/plotting.py:51: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if geom is not None and geom.type.startswith(prefix) and not geom.is_empty:
Out[9]:
Text(1, 0.03, 'bron: RIVM update 2023-04-04 & CBS statistiek')

Trends¶

In [10]:
g = sns.FacetGrid(data=sum7d_totals[(sum7d_totals.Date > '2021-11-30')], col="GGD_name", hue="Age_group", col_wrap=5, margin_titles=True, legend_out=True, sharey=False)
g = g.map_dataframe(sns.lineplot, x='Date', y='growth')
g = g.map(plt.axhline, y=0.0, ls="-", c=".8", zorder=1)
g = g.map_dataframe(sns.lineplot, x='Date', y='growth')

g.set_axis_labels("", "Groei percentage")

for ax in g.axes:
  #ax.xaxis.set_major_formatter(mdates.DateFormatter('%V'))
  #ax.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MONDAY, interval=1))
  ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(mdates.AutoDateLocator()))

g.set_titles(col_template = '{col_name}')
g.add_legend(loc='upper right')

g.despine()
plt.tight_layout()
plt.subplots_adjust(top=0.94)
g.fig.suptitle('Groei ratios (7d gemiddelde) per leeftijfsgroep', size=16.0, weight='bold')
g.fig.text(1,0, "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d') + " & CBS statistiek", ha="right", fontsize=12, color='grey')
#plt.subplots_adjust(hspace=0.1, wspace=0.1)
Out[10]:
Text(1, 0, 'bron: RIVM update 2023-04-04 & CBS statistiek')
In [11]:
def age_details(ggdName):
  dt = sum7d_totals[(sum7d_totals.Date > '2021-11-30') & (sum7d_totals.GGD_name == ggdName)]
  s = sns.lineplot(data=dt, x="Date", y="growth", hue="Age_group")
  plt.axhline(y=0.0, ls=":", c="0.6", zorder=1)
  tuftefy(s)
  #s.xaxis.set_major_formatter(mdates.DateFormatter('%V'))
  #s.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MONDAY, interval=1))
  s.xaxis.set_major_formatter(mdates.ConciseDateFormatter(mdates.AutoDateLocator()))
  s.set(xlabel="", ylabel="Groei (%)")
  s.set_title("Groei per leeftijdsgroup in " + ggdName, fontdict={'fontsize':14,'fontweight': 'bold'})
  s.text(dt.Date.min(), dt.growth.min(), "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d'), ha="left", fontsize=10, color='grey')
  plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0)
  plt.show()
  plt.close()

for ggd in sum7d_totals.GGD_name.unique():
    age_details(ggd)
In [12]:
g = sns.FacetGrid(data=sum7d_totals[(sum7d_totals.Date > '2021-11-30')], col="GGD_name", hue="Age_group", col_wrap=5, margin_titles=True, legend_out=True, sharey=True)
g = g.map_dataframe(sns.lineplot, x='Date', y='Positive_cases_per100k')
#g = g.map(plt.axhline, y=0.0, ls="-", c=".8", zorder=1)
#g = g.map_dataframe(sns.lineplot, x='Date', y='growth')

g.set_axis_labels("", "Aantal positief per 100.000 inwoners")

for ax in g.axes:
  #ax.xaxis.set_major_formatter(mdates.DateFormatter('%V'))
  #ax.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MONDAY, interval=1))
  ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(mdates.AutoDateLocator()))
  ax.set(yscale='symlog', ylim=[0, None])

g.set_titles(col_template = '{col_name}')
g.add_legend(loc='upper right')

g.despine()
plt.tight_layout()
plt.subplots_adjust(top=0.94)
g.fig.suptitle('Aantal positieve tests (7d gemiddelde) per leeftijfsgroep', size=16.0, weight='bold')
g.fig.text(1,0, "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d') + " & CBS statistiek", ha="right", fontsize=12, color='grey')
#plt.subplots_adjust(hspace=0.1, wspace=0.1)
Out[12]:
Text(1, 0, 'bron: RIVM update 2023-04-04 & CBS statistiek')
In [13]:
def age_details_absolute(ggdName):
  dt = sum7d_totals[(sum7d_totals.Date > '2021-11-30') & (sum7d_totals.GGD_name == ggdName)]
  s = sns.lineplot(data=dt, x="Date", y="Positive_cases_per100k", hue="Age_group")
  tuftefy(s)
  s.xaxis.set_major_formatter(mdates.ConciseDateFormatter(mdates.AutoDateLocator()))
  s.set(yscale='symlog', ylim=[0, None])
  s.set(xlabel="", ylabel="Positieve testen per 100.000 inwoners")
  s.set_title("Positieve tests per leeftijfsgroep in " + ggdName, fontdict={'fontsize':14,'fontweight': 'bold'})
  s.text(dt.Date.min(), 0.5, "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d'), ha="left", fontsize=10, color='grey')
  plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0)
  plt.show()
  plt.close()

for ggd in sum7d_totals.GGD_name.unique():
    age_details_absolute(ggd)
In [14]:
g = sns.FacetGrid(data=sum7d_totals[(sum7d_totals.Date > '2021-10-30') & (sum7d_totals.Age_group != "90+")], col="Age_group", hue="GGD_name", col_wrap=3, margin_titles=True, legend_out=True, sharey=True)
g = g.map_dataframe(sns.lineplot, x='Date', y='growth')
g = g.map(plt.axhline, y=0.0, ls="-", c=".8", zorder=1)
g = g.map_dataframe(sns.lineplot, x='Date', y='growth')

g.set_axis_labels("", "Groei percentage")

for ax in g.axes:
  #ax.xaxis.set_major_formatter(mdates.DateFormatter('%V'))
  #ax.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MONDAY, interval=1))
  ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(mdates.AutoDateLocator()))

g.set_titles(col_template = '{col_name}')
#g.add_legend(loc='upper right', bbox_to_anchor=(1.1,1.0))

g.despine()
plt.tight_layout()
plt.subplots_adjust(top=0.94)
g.fig.suptitle('Groei ratios (7d gemiddelde) per leeftijfsgroep', size=16.0, weight='bold')
g.fig.text(1,0, "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d'), ha="right", fontsize=12, color='grey')
#plt.subplots_adjust(hspace=0.1, wspace=0.1)
Out[14]:
Text(1, 0, 'bron: RIVM update 2023-04-04')
In [15]:
g = sns.FacetGrid(data=avg[(avg.Date > '2021-10-30') & (avg.Age_group != "90+")], col="Age_group", col_wrap=3, margin_titles=True, sharey=True)
g = g.map_dataframe(plt.fill_between, x='Date', y1='min', y2='max', alpha=0.2, color="#117733")
g = g.map_dataframe(sns.lineplot, x='Date', y='median', color='#117733')
#g = g.map_dataframe(sns.lineplot, x='Date', y='median', linestyle=":")
g = g.map(plt.axhline, y=0.0, ls="-", c=".8", zorder=1)

g.set_axis_labels("", "Groei percentage")

for ax in g.axes:
  #ax.xaxis.set_major_formatter(mdates.DateFormatter('%V'))
  #ax.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MONDAY, interval=1))
  ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(mdates.AutoDateLocator()))

g.set_titles(col_template = '{col_name}')
#g.add_legend(loc='upper right', bbox_to_anchor=(1.1,1.0))

g.despine()
plt.tight_layout()
plt.subplots_adjust(top=0.94)
g.fig.suptitle('Groei ratios (7d gemiddelde) per leeftijfsgroep, range over GGDs', size=16.0, weight='bold')
g.fig.text(1,0, "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d'), ha="right", fontsize=12, color='grey')
#plt.subplots_adjust(hspace=0.1, wspace=0.1)
Out[15]:
Text(1, 0, 'bron: RIVM update 2023-04-04')
In [16]:
g = sns.FacetGrid(data=avg_absolutes[(avg_absolutes.Date > '2021-10-30') & (avg_absolutes.Age_group != "90+")], col="Age_group", col_wrap=3, margin_titles=True, sharey=True)
g = g.map_dataframe(plt.fill_between, x='Date', y1='min', y2='max', alpha=0.2, color="#117733")
g = g.map_dataframe(sns.lineplot, x='Date', y='median', color='#117733')
#g = g.map_dataframe(sns.lineplot, x='Date', y='median', linestyle=":")
#g = g.map(plt.axhline, y=0.0, ls="-", c=".8", zorder=1)

g.set_axis_labels("", "Positieve testen per 100.000")

for ax in g.axes:
  #ax.xaxis.set_major_formatter(mdates.DateFormatter('%V'))
  #ax.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MONDAY, interval=1))
  ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(mdates.AutoDateLocator()))
  ax.set(yscale='symlog', ylim=[0, None])

g.set_titles(col_template = '{col_name}')
#g.add_legend(loc='upper right', bbox_to_anchor=(1.1,1.0))

g.despine()
plt.tight_layout()
plt.subplots_adjust(top=0.94)
g.fig.suptitle('Positieve testen (7d gemiddelde) per leeftijfsgroep, range over GGDs', size=16.0, weight='bold')
g.fig.text(1,0, "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d'), ha="right", fontsize=12, color='grey')
#plt.subplots_adjust(hspace=0.1, wspace=0.1)
Out[16]:
Text(1, 0, 'bron: RIVM update 2023-04-04')
In [17]:
import pylab as pl
currentDt = sum7d_totals[(sum7d_totals.Date > '2021-10-30') & (sum7d_totals.Age_group != "90+")]

yMin = currentDt.growth.min()
yMax = currentDt.growth.max()

xMin = currentDt.Date.min()
xMax = currentDt.Date.max()

def hexbin(x, y, color, **kwargs):
    cmap = sns.light_palette(color, as_cmap=True)
    plt.hexbin(pl.date2num(x), y, gridsize=len(x.unique()), cmap=cmap, extent=[pl.date2num(xMin), pl.date2num(xMax), yMin, yMax], **kwargs)

g = sns.FacetGrid(data=currentDt, col="Age_group", col_wrap=3, margin_titles=True, legend_out=True, sharey=True)
g = g.map(hexbin, 'Date', 'growth', color='black')
g = g.map(plt.axhline, y=0.0, ls="-", c=".8", zorder=1)
#g = g.map_dataframe(sns.lineplot, x='Date', y='growth')

g.set_axis_labels("", "Groei percentage")

for ax in g.axes:
  #ax.xaxis.set_major_formatter(mdates.DateFormatter('%V'))
  #ax.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MONDAY, interval=1))
  ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(mdates.AutoDateLocator()))

g.set_titles(col_template = '{col_name}')
#g.add_legend(loc='upper right', bbox_to_anchor=(1.1,1.0))

g.despine()
plt.tight_layout()
plt.subplots_adjust(top=0.94)
g.fig.suptitle('Groei ratios (7d gemiddelde) per leeftijfsgroep', size=16.0, weight='bold')
g.fig.text(1,0, "bron: RIVM update " + dateOfStats.strftime('%Y-%m-%d'), ha="right", fontsize=12, color='grey')
#plt.subplots_adjust(hspace=0.1, wspace=0.1)
Out[17]:
Text(1, 0, 'bron: RIVM update 2023-04-04')