Covid19 vs Grypa: wpływ wirusa Covid-19 na ilość przypadków grypy w Polsce i Europie

Opublikowano: June 8, 2021 przez Mariusz Borycki

Photo by Fusion Medical Animation on Unsplash

 

Jednym z najbardziej powszechnych raportów analizowanych w ostatnim roku 2020, jest ten pokazujący ilość zakażeń na Covid19. Ja natomiast chciałbym się nad tym pochylić z nieco innej strony. Mianowicie, mówi się że jeśli można wskazać coś pozytywnego w pandemii z lat 2020/2021, to będzie to pokonanie wirusa grypy. Przy pomocy krókiej analizy chciałem sprawdzić czy naprawdę koronawirus wpłynął na znaczne zmniejszenie tudzież całkowite pokonanie grypy zarówno w Europie jak i lokalnie w Polsce. 

 

Żródło danych:

Dane dotyczące ilości stwierdzonych przypadków Covid19 i wirusa grypy zostały pobrane z dwóch różnych źródeł:

 

Grypa:

Aby pobrać dane dotyczące grypy należy wejść na powyższą stronę internetową oraz przefiltrować widoczny na niej raport przez interesujący nas okres oraz kraje, po czym plik w postaci arkusza kalkulacyjnego będzie gotowy do pobrania.

Mariusz Borycki - flu_report

Flu Virus Characteristics - https://flunewseurope.org/VirusCharacteristics

 

Przekształcanie / Czyszczenie Danych:

Pobrany plik przerobiłem z arkusza kalulacyjnego na format .csv i przeniosłem go do mojego repozytorium na GitHub. Narzędziem, którego najczęściej używam w procesie analizy danych jest Jupyter Notebook.

Na początek należy pobrać wszystkie niezbędne biblioteki, z których będę korzystał oraz pierwszy plik, zawierający ilość stwierdzonych przypadków wirusa grypy, którego roboczo nazwałem "flu_detected".

import pandas as pd
import os
from pathlib import Path
from bs4 import BeautifulSoup
import requests
import re
import io

url_flu = "https://raw.githubusercontent.com/mborycki/Covid_Influenza_Comparison/main/Influenza_virus_detections_in_Europe.csv"

flu_detected = pd.read_csv(url_flu)
flu_detected.head()


Mariusz Borycki - flu_detected

 

Jak widać tabelka przedstawia 11 kolumn. Na początku zobaczyłem co zawiera kolumna „Region”, a są tam dwie wartości:

  • EU/EEA - czyli kraje wchodzące w skład Europejskiego Obszaru Gospodarczego
  • WHO Europe - wszystkie kraje Europejskie

 

Myślę, że w tej tabeli występują duplikaty, bo jeśli kraj należy do Europejskiego Obszaru Gospodarczego, to dane dla tego kraju będą zarówno w „EU/EEA” jak i w „WHO Europe”. Natomiast warto to sprawdzić na przykładzie wybranego kraju. Niech to będzie Polska, która jest częścią EEA:

 

Mariusz Borycki - flu_detected-unique

 

Jak widać, zarówno w „EEA” jak i „WHO Europe” mamy dla Polski te same wartości. W związku z tym zostawiłem tylko wartości przypisane do "WHO Europe", w którego skład wchodzą kraje zarówno z "EEA" jak i te, które nie są częścią strefy wolnego handlu.


Zerknąłem na kilka szczegółów:
Mariusz Borycki - flu_detected-info

 

Jak widać mamy do czynienia z 9 763 wierszami oraz 11 kolumnami. Widzimy również typy danych (liczba całkowita „int64” czy text „object”) oraz wiemy, że tabela nie zawiera pustych wartości, jako że każda kolumna posiada tyle samo wierszy.


Następnie, na podstawie naszej tabelki zaplanowałem kilka zadań do wykonania:

  • Podzielić kolumnę „Week” zawierającą de facto rok i tydzień na dwie osobne kolumny
  • Zobaczyć czy kolumna "Surveillance System Type" będzie mi potrzebna
  • Zastanowić się czy potrzebuję kolumny "Season" i "Region". Jeśli nie, to należy je usunąć
  • Zobaczyć (z czystej ciekawości) jaki jest udział każdego typu grypy w stosunku do jej sumy stwierdzonych przypadków
  • Zsumować wszystkie typy grypy, jako że finalnie potrzebowałem jednej wartości (tylko sumę)
  • Stworzyć tabelę przestawną, która ułatwi analizę

 

Zacząłem od zamiany nazwy kolumny z "Week" na "YearWeek", jako że wartości w tej kolumnie to właśnie rok i tydzień (patrz tabela wyżej):

flu_detected.rename(columns={'Week':'YearWeek'},inplace=True)

 

Następnie, sprawdziłem unikalne wartości w kolumnach "Surveillance System Type", w której była tylko jedna zmienna: "Non-sentinel", oraz w kolumnie "Season", w której z kolei znajdują się następujące wartości:

flu_detected['Surveillance System Type'].unique()

out: ['Non-sentinel']

 

flu_detected['Season'].unique()

out: ['2015/2016', '2016/2017', '2017/2018', '2018/2019', '2019/2020', '2020/2021']

 

Postanowiłem usunąć zarówno kolumnę "Surveillance System Type", zawierającą tylko jedną nieznaczącą dla mnie wartość jak i "Season", która w zasadzie jest uszczuploną wersją kolumny "YearWeek":

flu_detected = flu_detected.drop(['Season','Region','Surveillance System Type'],axis=1)

 

Kolejnym krokiem jest dodanie kolumny z sumą całkowitą dla wszystkich typów grypy:

 

Mariusz Borycki - flu_detected-total_cases

 

Teraz czas na stworzenie tabeli przestawnej, która poprawi czytelność powyższych danych:

Mariusz Borycki - flu_detected-pivot_table

 

Myślę, że tabelka wygląda już o wiele lepiej. Aktualnie wszystkie nazwy typów grypy znajdują się w kolumnie „Flu Type”, wartości występują w kolumnie „Detected_Cases”, a kolumna "YearWeek" została podzielona na dwie osobne "Year" i "Week".


Co prawda, skupiałem się na sumie wartości zachorowań, ale chciałem również zobaczyć udział zachorowań dla każdego typu grypy. Zanim to zrobiłem, postanowiłem najpierw nieco skrócić nazwę dla typów grypy, by wykres był nieco czytelniejszy:

original_type_names = ['A not subtyped', 'A(H1)pdm09', 'A(H3)', 'B lineage not determined', 'B/Vic', 'B/Yam']

new_type_names = ['A', 'A(H1)', 'A(H3)','B', 'B/Vic', 'B/Yam']

 

for o, n in zip(original_type_names,new_type_names):
    flu_detected2.loc[(flu_detected2['Flu Type'] == o),'Flu Type']=n

 

Teraz wartości w kolumnie "Flu Type" wyglądają następująco:

flu_detected2['Flu Type'].unique()

out: ['A', 'A(H1)', 'A(H3)', 'B', 'B/Vic', 'B/Yam', 'Total Detected Cases']

 

Chciałbym jeszcze sprawdzić czy posiadamy wystarczająco danych dla każdego roku. Aby to zrobić, zobaczyłem sumę zdiagnozowanych przypadków grypy oraz ilość tygodni zawartych w danym roku:

flu_detected2[(flu_detected2['Flu Type'] == 'Total Detected Cases')].sort_values(['Year']).groupby(['Flu Type', 'Year'])['Detected_Cases'].sum().reset_index()


Mariusz Borycki - flu_detected_cases

 

years = flu_detected2.Year.unique()

for year in years:
    print(f'In {year} we have {len(flu_detected2[flu_detected2.Year==year].Week.unique())} weeks')

 

Mariusz Borycki - flu_detected_weeks

 

Jak widać na powyższym przykładzie rok 2015 jest niepełny (mamy dane dla 14 tygodni). Oczywiście, rok 2021 nie wygląda dużo lepiej. Natomiast, wynika to z faktu, że dzień, za który pobrałem dane to koniec maja 2021 roku. W takim razie usuniemy rok 2015 z tabeli, by nie zaburzać percepcji:

years_list = ['2016','2017','2018','2019','2020', '2021'] 

flu_detected2 = flu_detected2[flu_detected2['Year'].isin(years_list)]

 

Następnie zobaczyłem jak wygląda udział typów grypy w podziale na lata 2016-2021:

df1 = flu_detected2[flu_detected2['Flu Type']!='Total Detected Cases'].groupby(['Flu Type', 'Year'])['Detected_Cases'].sum().reset_index()

df2 = df1.pivot(index="Year", columns="Flu Type", values="Detected_Cases").reset_index().set_index('Year')

 

fig, ax1 = plt.subplots()
plt.rcParams["figure.figsize"] = (25,15)
plt.xticks(fontsize=16, rotation=45)
plt.grid(color='grey', linestyle = '--', linewidth = 0.5)

 

width = 0.8
bottom = 0

 

for i in df2.columns:
    plt.bar(df2.index, df2[i], width=width, bottom=bottom)
    bottom += df2[i]

 

plt.title(f"Influenza Cases per year in Europe", fontsize=28)
plt.xlabel('Years', fontsize=24)
plt.ylabel("Detected Flu Cases", color='black', fontsize=24)
plt.tick_params(axis='y', labelcolor='black', labelsize=16) 
plt.legend(df2.columns, fontsize=16)
plt.tight_layout()

 

Mariusz Borycki - flu_cases-bar_chart_Europe

 

Jak widać na powyższym wykresie rok 2021 był praktycznie wolny od wirusa grypy. Co do pozostałych lat, to niemal w każdym roku najpowrzechniejszy typ wirusa grypy, to typ A występujący zarówno u ludzi jak i zwierząt (świnie, konie, foki, norki, wieloryby i ptaki), oraz typ B, który występuje tylko u ludzi. Na temat definicji dla każdego rodzaju grypy można znaleźć sporo infrmacji m.in na Wikipedii, do czego zachęcam. 

 

Nie potrzebowałem już danych dla poszczególnych typów grypy, tak więc stworzyłem kolejną tabelkę zawierającą wartości sumaryczne. Tabelę nazwałem "df_flu":

df_flu = flu_detected2[(flu_detected2['Flu Type']=='Total Detected Cases')].sort_values(['Year']).groupby(['Country','Year', 'Week'])['Detected_Cases'].sum().reset_index()

 

Tu zobaczyłem sobie sumaryczną wartość zachorowań na grypę w latach 2016-2021:

xs = df_flu.groupby('Year')['Detected_Cases'].sum().reset_index()['Year']
ys = df_flu.groupby('Year')['Detected_Cases'].sum().reset_index().Detected_Cases.values

 

plt.rcParams["figure.figsize"] = (15,10)
plt.plot(xs,ys,'bo-')
plt.title(f'Total influenza cases for all countries', fontsize=24)

 

for x,y in zip(xs,ys):
    label = f'{y:,}'
    plt.annotate(label, (x,y), textcoords="offset points", xytext=(0,10), ha='center') 
plt.grid(color = 'green', linestyle = '--', linewidth = 0.5)

 

plt.show()

 

Mariusz Borycki - flu_cases-line_chart_Europe

 

Na pierwszy rzut oka widać spadek zachorowań na grypę w latach 2019 - 2021 (Maj). Co prawda dane za maj są niekompletne, ale (o ile pamiętam) najwięcej zachorowań przypada w pierwszym kwartale każdego roku. Natomiast nieco później sobie to jeszcze sprawdziłem.

 

Na koniec usuniemy jeszcze literkę "W" z kolumny "Week", dzięki czemu będziemy mieć kolumnę z liczbami całkowitymi przedstawiającymi numer tygodnia - "1" zamiast "W01":

df_flu['Week'] = df_flu['Week'].map(lambda x: x.lstrip('W'))


df_flu['Week'] = df_flu['Week'].astype('int')


df_flu['Year'] = df_flu['Year'].astype('int')

 

Gotowe, ostatni rzut oka na finalną tabelkę z danymi pokazującymi ilość zachorowań na wirusa grypy w Europie:

 

Mariusz Borycki - flu_detected_sorted.jpg

 

Czas na drugi raport. Tym razem zobaczyłem jaka była ilość zakażeń na wirusa SARS-COV-2 w Europie. Finalnie druga tabelka będzie miała taką formę jak ta powyżej (dla grypy), po to by móc je ze sobą połączyć i wykonać porównanie.

 


COVID:

 

Z kolei jeśli chodzi o raport dla wirusa Covid19, to wszystkie dane, których użyłem zostały pobrane z repozytorium Centrum Nauki i Inżynierii Systemowej (CSSE) na Uniwersytecie Johnsa Hopkinsa.
Adres strony: https://github.com/CSSEGISandData/COVID-19 


Na podstawie tych danych został opracowany bardzo popularny wykres przedstawiający aktualną sytuację związaną z pandemią Covid19.

 

Do pobrania raportów z powyższego repozytorium na GitHub użyłem biblioteki "Beautiful Soup". Linki do każdego z raportu zostały zapisane do zmiennej "urls". Natomiast daty dla każdego raportu zostały zapisane w zmiennej "df_list_names":

url = "https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_daily_reports"
r = requests.get(url)

 

html_doc = r.text
soup = BeautifulSoup(html_doc)
a_tags = soup.find_all('a')

 

urls = ['https://raw.githubusercontent.com'+re.sub('/blob', '', link.get('href'))
        for link in a_tags if '.csv' in link.get('href')]

 

df_list_names = [url.split('.csv')[0].split('/')[url.count('/')] for url in urls]

 

Rzut oka na zmienną "urls" oraz "df_list_names":

urls[:2]

out:

['https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/01-01-2021.csv',
'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports/01-02-2021.csv']

 

df_list_names[:5]

out: ['01-01-2021', '01-02-2021', '01-03-2021', '01-04-2021', '01-05-2021']

 

Pobrane pliki z repozytorium, zawierają następujące kolumny:

FIPS, Admin2, Province_State, Country_Region, Last Update, Lat and Long_, Confirmed, Deaths, Recovered, Active, Incident_Rate, Case_Fatality_Ratio (%)

 

Zadecydowałem jednak, że będę potrzebować poniższych kolumn:

Country_Region, Last_Update, Confirmed, Deaths, Recovered.

 

Dodatkowo pobrałem, również kolumny: Lat, Long_

 

Pobierając dane okazało się, że w ciągu roku nazwy kolumn się delikatnie zmieniały. Z uwagi na to musiałem dodać do kodu instrukcje warunkowe "if, else":

col_names1 = ['Country_Region','Last_Update','Lat','Long_','Confirmed','Deaths','Recovered']


col_names2 = ['Country/Region','Last Update','Latitude','Longitude','Confirmed','Deaths','Recovered']


col_names3 = ['Country/Region','Last Update','Confirmed','Deaths','Recovered']

for count, url in enumerate(urls):
    download = requests.get(url).content
    df = pd.read_csv(io.StringIO(download.decode('utf-8')))


    if (df.shape[1] == 14) | (df.shape[1] == 12):
        df = df[col_names1]


    elif df.shape[1] == 8:
        df = df[col_names2]


    elif df.shape[1] == 6:
        df = df[col_names3]
        df['Lat'] = 0
        df['Long_'] = 0
        df = df[['Country/Region','Last Update','Lat','Long_','Confirmed','Deaths','Recovered']]


    else:
        print(f'We have {df.shape[1]} columns in {url} file')
    
    df['File_Name'] = df_list_names[count]        


    try:
        df.columns = cols 
        covid_table = covid_table.append(df, ignore_index=True)


    except:
        pass

 

Rzut oka na pobrane dane:

 

Mariusz Borycki - covid-head

 

Przekształcanie / Czyszczenie danych:

Kolejnym krokiem będzie zmiana typu danych dla dwóch kolumn "Last_Update" i "File_Name"

 

Mariusz Borycki - covid_to-datatime

 

Jak widać powyżej mamy kilka kolumn bez wartości, co zamierzam poprawić:

df_covid.fillna({'Deaths':0,'Confirmed':0,'Recovered':0},inplace=True)

covid_cases_list = ['Confirmed','Deaths','Recovered']


for case in covid_cases_list:
    df_covid[case] = df_covid[case].astype(float)

 

Kolejny krok to podsumowanie ilości przypadków: potwierdzonych/śmiertelnych/ozdrowień po kraju i kolumnie "Last_Update":

df_covid = df_covid.groupby(['Country_Region','Last_Update']).agg({'Confirmed':'sum','Deaths':'sum','Recovered':'sum'}).reset_index()

 

Kolumna "Last update" wskazuje datę dla danych. Natomiast, by móc połączyć tę tabelkę z tabelą zawierającą dane dla wirusa grypy oraz by móc je ze sobą porównać, potrzebowałem numeru tygodnia dla każdego dnia, do czego posłużyła mi funkcja "isocalendar":

week_no = []
year_no = []


for value in df_covid['Last_Update']:
    week_no.append(value.isocalendar()[1])
    year_no.append(value.isocalendar()[0])

 

df_covid['Week'] = week_no
df_covid['Year'] = year_no

 

Poniżej sprawdziłem sobie jak tabelka na przykładzie Polski wygląda po zmianach. Wybrałem tydzień 20 z 2021 roku:

df_covid[(df_covid.Country_Region=='Poland')&(df_covid.Week==20)&(df_covid.Year==2021)]

 

Mariusz Borycki - covid-table

 

Jako że potrzebowałem danych w ujęciu tygodniowym, a nie osobno dla poszczególnych dni w tygodniu, to wyciągnąłem z powyższej tabeli wartości maksymalne gdyż są to wartości wskazujące ilość zakażeń na koniec tygodnia:

df_covid = df_covid.groupby(['Country_Region','Week','Year'],sort=False).agg({'Confirmed':'max','Deaths':'max','Recovered':'max'}).reset_index()

 

Zmieniłem też nazwę kolumny dla regionu:

df_covid.rename(columns={'Country_Region':'Country'},inplace=True)

 

Mariusz Borycki - covid-head2

 

Teraz wszystko wydaje się być w porządku. Natomiast, jeszcze jedna kwestia mnie zastanawia. Mianowicie, czy w obu tabelach są dokładnie takie same nazwy krajów:

 

Mariusz Borycki - covid_flu-country_names

 

Moja główna tabela z danymi dotyczącymi grypy, zawieraa tylko kraje europejskie. Dlatego z tabeli zawierającej dane dla koronawirusa, wyciągnąłem również kraje europejskie. Jak widać, mamy kilka brakujących wartości w tabeli "df_covid"  (kolumna "cov"):

 

Mariusz Borycki - covid_flu-missing_countries_print

 

Stworzyłem listę z krajami do zmiany i odświeżyłem tabelę:

 

Mariusz Borycki - covid_flu-missing_countries_func

 

Zmieniłem nazwę dla kolumny "Detected Cases":

df_flu.rename(columns={'Detected_Cases':'Detected_FluCases'},inplace=True)

 

Połączyłem te dwie tabele ze sobą oraz sprawdziłem, w kórych komórkach nie było wartości dla 2021 roku. Wszystkie puste wiersze zamieniłem na wartości zerowe. Mówiąc wprost, potrzebowałem wartości liczbowych w całej kolumnie:

final_df = pd.merge(df_covid,df_flu,on=['Country','Year','Week'],how='right').sort_values(['Year','Week','Country'])

final_df.fillna({'Deaths':0,'Confirmed':0,'Recovered':0},inplace=True)

 

Na potrzebę analiz i przejrzystości wykresu dodam jeszcze kwartały:

quarters = pd.DataFrame(columns={"Week","Quarter"})
def quarter(x): 
    if (x <= 13):
        return 1
    elif (x <= 26):
        return 2
    elif (x <= 39):
        return 3
    else:
        return 4

 

quarters['Week'] = final_df.Week.unique()
quarters['Quarter'] = quarters['Week'].apply(quarter)

final_df = final_df.merge(quarters,on='Week',how='inner')

 

Mariusz Borycki - covid_flu-info

 

Aktualnie mam 9 359 wierszy, nie brakuje tygodni, nie mam pustych wierszy, ani ujemnych wartości. Wszystko wygląda w porządku, więc mogłem zapisać plik na dysku, po czym wrzucić go do mojego repozytorium i na tym następnie pracować w kolejnym etapie:

final_df.to_csv('Covid_and_Influenza.csv',index=False)

 

Analiza i wizualizacje:

Do analizy stworzyłem osobny plik w Jupyter Notebook. Oczywiście, zacząłem od pobrania bibliotek oraz samego pliku:

import pandas as pd
import matplotlib.pyplot as plt

url = "https://raw.githubusercontent.com/mborycki/Covid_Influenza_Comparison/main/Covid_and_Influenza.csv"

df = pd.read_csv(url)

 

Warto sobie przypomnieć nazwy kolumn w tabeli oraz wyjaśnić ich znaczenie:

  • Country: Nazwa kraju
  • Week: Numer tygodnia
  • Confirmed: IIość potwierdzonych przypadków wirusa SARS-CoV-2
  • Deaths: IIość śmiertelnych przypadków na SARS-CoV-2
  • Recovered: Ilość ozdrowieńców (SARS-CoV-2)
  • Detected_FluCases: Ilość zdiagnozowanych osób z chorych na grypę
  • Quarter: Kwartał

 

Poniżej wypisałem kilka punktów, które chiałbym jeszcze zobaczyć na podstawie tabeli, którą wcześniej przygotowałem:

  1. Jak wyglądał poziom grypy w ujęciu tygodniowym (dla Europy i Polski)
  2. Jak wyglądał poziom Covid19 w ujęciu tygodniowym (dla Europy i Polski)
  3. Top 10 krajów z grypą / Covid19
  4. Na koniec sprawdź, ile zachorowań na grypę mieliśmy po kwartale 2 roku 2020

 

AD1. Jak wyglądał poziom grypy w ujęciu tygodniowym (dla Europy i Polski)

 

Aby zobaczyć historię grypy stworzyłem poniższą funkcję:

def WeeklyFluChart(table, where):
    """
    THE CHART SHOWS WEEKLY CASES DETECTION FOR FLU WITHIN YEARS 
    
    table: dataframe with influenza cases (DataFrame)
    where: country we are interested in. Required for a chart title (String/Object)
    """

    years = table.Year.unique()
    color_per_year = ['green', 'blue', 'yellow', 'orange', 'purple', 'red']

 

    fig, ax1 = plt.subplots()
    plt.rcParams["figure.figsize"] = (25,15)
    plt.xticks(fontsize=16, rotation=45)
    plt.grid(color='grey', linestyle = '--', linewidth = 0.5)

 

    for number, year in enumerate(years):
        color = color_per_year[number]

        x = table[table.Year==year].Week.unique()
        y = table[table.Year==year].groupby(['Week', 'Year'])['Detected_FluCases'].sum().reset_index().sort_values(['Year','Week'])['Detected_FluCases']
        plt.title(f"Influenza Cases per year in {where}", fontsize=28)
        plt.xlabel('Weeks', fontsize=24)
        plt.ylabel("Detected Flu Cases", color='black', fontsize=24)
        plt.plot(x, y, color=color)
        plt.tick_params(axis='y', labelcolor='black', labelsize=16) 
        plt.legend(years, fontsize=16)

 

Używając powyższej funkcji sprawdziłem wynik:

WeeklyFluChart(df, 'Europe')

 

Mariusz Borycki - flu_cases-line_chart_Europe_yearly

 

Najwyższy poziom grypy miał miejsce w 2018 i 2019 roku. W 2021 wykrywalność grypy była bliska zera. Oczywiście, dane nie zawierają pełnego roku 2021, ale największy wzrost wykrywalności występuje między piątym, a dziesiątym tygodniem każdego roku, a w 2021 roku nie widać żadnego wzrostu w analogicznym tygodniu.

 

Jak wygląda ten sam raport, ale dla Polski. Użyłem tej samej funkcji:

WeeklyFluChart(df[df.Country=='Poland'],'Poland')

 

Mariusz Borycki - flu_cases-line_chart_Poland_yearly.jpg

 

Wykres wygląda podobnie jak w przypadku Europy. Jednak największy wzrost odnotowaliśmy w 2016 roku i widać naprawdę niewielki wzrost wykrywalności grypy po 50 tygodniu (w Europie w tym samym czasie mieliśmy większą liczbę stwierdzonych przypadków grypy). To, co jest wspólne dla Europy i Polski, to praktycznie brak przypadków grypy w 2021 roku.

 

AD2. Jak wyglądał poziom Covid19 w ujęciu tygodniowym (dla Europy i Polski)

 

To co wiemy na temat pandemii, to fakt, że przed rokiem 2020 nie było oficjalnie stwierdzonych przypadków tego wirusa. Możemy to potwierdzić za pomocą poniższej linijki kodu:

df[df.Confirmed>0].Year.unique()

out: [2021, 2020]

 

Chciałbym zobaczyć wyniki dla Covid19 na wykresach i porównać je z analogicznymi danymi dla grypy. Postanowiłem więc usunąć wartości dla tygodni z mojej tabeli i zachować tylko lata i kwartały. Nowe dane umieściłem w tabeli o nazwie "df_q":

df_q = df[['Country','Year','Quarter','Confirmed','Deaths','Recovered','Detected_FluCases']].groupby(['Country','Year','Quarter'])\

.agg({'Confirmed':'max','Deaths':'max','Recovered':'max','Detected_FluCases':'sum'}).sort_values(['Country','Year','Quarter'])\

.reset_index().sort_values(['Country','Year','Quarter'])

 

Teraz możemy napisać funkcję dla naszego wykresu:

def CovidChart(table,where):
    """
    THE CHART SHOWS WEEKLY CASES DETECTION FOR COVID IN QUARTERLY LEVEL 
    
    table: dataframe with covid cases (DataFrame)
    where: country we are interested in. Required for a chart title (String/Object)
    """


    tbl = table[table.Year>=2020].groupby(['Year','Quarter'])\
    .agg({'Confirmed':'sum', 'Deaths':'sum', 'Recovered':'sum','Detected_FluCases':'sum'})\
    .sort_values(['Year','Quarter']).reset_index()

    # Create a new column for Year and Quarters
    tbl['YearQuarter'] = tbl.Year.astype(str)+'-Q'+tbl.Quarter.astype(str)

 

    fig, ax1 = plt.subplots()
    plt.rcParams["figure.figsize"] = (25,15)
    plt.xticks(fontsize=14, rotation=45)
    plt.grid(color='grey', linestyle = '--', linewidth = 0.5)

 

    x = tbl.YearQuarter.sort_values().unique()
    y = tbl.groupby(['YearQuarter'])['Confirmed'].sum().reset_index().sort_values(['YearQuarter'])['Confirmed']
    plt.title(f"Covid19 Cases per year in {where}", fontsize=28)
    plt.xlabel('Quarters', fontsize=18)
    plt.ylabel("Detected Covid19 Cases", color='black', fontsize=18)
    plt.bar(x, y, color='grey')
    plt.tick_params(axis='y', labelcolor='black', labelsize=16) 

 

    for xx,yy in zip(x,y):
        label = f'{yy:,}'
        plt.annotate(label, (xx,yy), textcoords="offset points", xytext=(0,10), ha='center', fontsize=16) 

CovidChart(df_q,'Europe')

 

Mariusz Borycki - covid_cases_bar_chart-Europe

 

Jak widać powyżej, mamy duży wzrost przypadków COVID w czwartym kwartale 2020 r. Pierwszy kwartał 2021 r. nie był znacznie lepszy. Natomiast widać wyraźną poprawę w II kwartale 2021 roku:

CovidChart(df_q[df_q.Country == 'Poland'],'Poland')

 

Mariusz Borycki - covid_cases_bar_chart-Poland

 

W Polsce mamy dość podobny trend jak to miało miejsce w Europie.

 

Teraz możemy stworzyć jeden wykres zawierający przypadki grypy i Covid2. Trzeba jednak pamiętać, że będzie to robione tylko po to, aby pokazać pewien trend, ponieważ w przypadku pandemii koronawirusa mamy do czynienia ze znacznie większą liczbą zakażeń niż w przypadku grypy.

 

Pierwsza funkcja dzieli wartości występujące w tabeli przez tysiąc. Zrobiłem to głównie po to, by nie pokazywać milionowych wartości na wykresie. Zaokrągliłem także liczby do dwóch miejsc po przecinku, co również zwiększy czytelność. Ostatnią kwestią jest stworzenie nowej kolumny będącej połączeniem lat i kwartałów, dzięki czemu będziemy wiedzieli np. którego roku dotyczy kwartał trzeci na wykresie:

# I made a function to have bigger visibility on chart
def CovidCasesDevider(table_name):
    covid_cases_list_mln = ['Confirmed','Deaths','Recovered','Detected_FluCases']

 

# number of cases divided by 1000
    for col in covid_cases_list_mln: 
        for value in range(len(table_name)):
            table_name.loc[value,(col)] = table_name.loc[value,(col)] / 1000

 

# rounded to 2 decimal values            
    for col in covid_cases_list_mln: 
        table_name[col] = table_name[col].apply(lambda x: round(x,2))

 

# Do not need weeks/year in chart - quarters is enough      
    table_name['YearQuater'] = table_name.Year.astype(str)+'-Q'+table_name.Quarter.astype(str)
    table_name = table_name.drop(["Year","Quarter"],axis=1)
    
    return table_name

 

A poniżej finalny kod dla wykresu przedstawiającego porównanie wykrywalnści na wirusa grypy i Covid19, którego częścią jest powyższa funkcja:

def VirusComparison(table,where):
    """
    THE CHART SHOWS QYARTERLY COMPARISON OF CASES DETECTION FOR COVID AND FLU 
    
    table: dataframe with detected cases (DataFrame)
    where: country we are interested in. Required for a chart title (String/Object)
    """

 

    # Chart Creation
    fig, ax1 = plt.subplots()
    plt.rcParams["figure.figsize"] = (25,15)
    plt.xticks(fontsize=16, rotation=45)
    plt.grid(color = 'green', linestyle = '--', linewidth = 0.5)

 

    # Data Aggregation
    chart = CovidCasesDevider(table.groupby(['Year','Quarter'])\
    .agg({'Confirmed':'sum', 'Deaths':'sum', 'Recovered':'sum','Detected_FluCases':'sum'})\
    .sort_values(['Year','Quarter']).reset_index())

 

    x = chart.YearQuater.unique()
    y = chart['Confirmed']
    z = chart['Detected_FluCases']

 

    # Covid19:
    ax1.set_title(f"Covid and Flu Cases Comparison in {where} ('000)", fontsize=28)
    color = 'tab:red'
    ax1.set_xlabel('Periods', fontsize=24)
    ax1.set_ylabel("Confirmed Covid19 Cases ('000)", color=color, fontsize=24)
    ax1.plot(x, y, color=color)
    ax1.tick_params(axis='y', labelcolor=color, labelsize=16) 

 

    for xx,yy in zip(x,y):
        label = "{:.0f}".format(yy)
        plt.annotate(label, (xx,yy), textcoords="offset points", xytext=(0,10), ha='right', fontsize=20) 

 

    # Influenza:
    ax2 = ax1.twinx()  
    color = 'tab:blue'
    ax2.set_ylabel("Detected Inluenza Cases ('000)", color=color, fontsize=24)  # we already handled the x-label with ax1
    ax2.plot(x, z, color=color)
    ax2.tick_params(axis='y', labelcolor=color, labelsize=16)

 

    for xx,zz in zip(x,z):
        label = "{:.1f}".format(zz)
        plt.annotate(label,(xx,zz),textcoords="offset points",xytext=(0,10),ha='right', fontsize=20)

 

    fig.tight_layout()  
    plt.show()

VirusComparison(df_q,'Europe')

 

Mariusz Borycki - covid_vs_flu_cases-line_chart_Europe.jpgWidoczna jest zależność między Covid19 i grypą. Kiedy pandemia dotarła do Europy, grypa niemalże zniknęła. Pamiętajmy, że wolumeny na wykresie są podzielone przez 1000.

 

Tak więc najwyższa liczba przypadków grypy miała miejsce w I kwartale 2018 r.: 184 900 przypadków
Z drugiej strony najwyższa liczba przypadków Covid19 była w II kwartale 2021 r.: 52 285 000 przypadków

 

Zobaczmy jak to wygladało w Polsce:

chosen_country = 'Poland' 


VirusComparison(df_q[df_q.Country==chosen_country],chosen_country)

 

Mariusz Borycki - covid_vs_flu_cases-line_chart_PolandW Polsce widać podobny trend w porównaniu do tego co widzimy na skale całej Europy

 

AD3. Top 10 krajów z grypą / Covid19

 

Kolejnym krokiem było sprawdzenie, w których krajach oraz w jakim roku wykryto najwięcej przypadków grypy oraz Covid19.

 

Najwięcej stwierdzonych przypadków grypy:

 

df_q.groupby(['Country','Year'])['Detected_FluCases'].max().sort_values(ascending=False).reset_index().drop_duplicates('Country').head(10).set_index('Country')


Mariusz Borycki - flu_cases-TOP10_Europe

 

Najwięcej stwierdzonych przypadków Covid19:

 

df_q.groupby(['Country','Year'])['Confirmed'].max().sort_values(ascending=False).reset_index().drop_duplicates('Country').head(10).set_index('Country')

Mariusz Borycki - covid_cases-TOP10

 

AD4. Na koniec sprawdzę, ile zachorowań na grypę mieliśmy po drugim kwartale roku 2020

 

df_q[(df_q.Year>=2020)&(df_q.Quarter>=2)].groupby(['Country','Year'])['Detected_FluCases'].max().sort_values(ascending=False).\

reset_index().drop_duplicates('Country').head(10).set_index('Country')

Mariusz Borycki - flu_cases-TOP10_Europe2

 

Wniosek:

Na podstawie przygotowanych przeze mnie danych możemy z całą pewnością stwierdzić, że pandemia SARS-CoV-2 wpłynęła na wykrywalność grypy. Jednakże ilość zachorowań na grypę nigdy (przynajmniej od 2016 r.) nie była nawet zbliżona do zasięgu pandemii Covid19 w całej Europie.

Skala koronawirusa jest niewiarygodnie duża i nie możemy mieć wątpliwości, że zostaliśmy dotknięci pandemią.

 

Wszystkie skrypty wraz z ich opisem znajdują się w moim repozytorium na platformie GitHub, na którą serdecznie zapraszam.

Comments:

0 comments

There is no comment yet.

Add new comment: