متى سينخفض ​​الوباء؟ التقييم في بايثون مع الباندا

صورة
تحية للجميع.

رأيت العديد من لوحات المعلومات على COVID-19 ، لكنني لم أجد بعد الشيء الرئيسي - توقعات وقت انخفاض الوباء. لذلك ، كتبت نص بايثون صغير. يأخذ بيانات من جداول منظمة الصحة العالمية حول جيثب ، ويحدد حسب البلد ، ويرسم خطوط الاتجاه. وهو يقوم بالتنبؤات بناءً عليها - عندما يمكن توقع انخفاض عدد الإصابات في كل بلد من أفضل 20 من حيث عدد حالات COVID-19. أعترف أنني لست خبيرا في مجال علم الأوبئة. تستند الحسابات أدناه إلى البيانات المتاحة للجمهور والحس السليم. يتم قطع جميع التفاصيل.

تحديث من 04/10/2020 - تم تحديث الجدول الرئيسي والرسوم البيانية.

تحديث 16/16/2020 - المستخدمh3ckslقام بتحديث الرسوم البيانية ونشرها على موقعه على الإنترنت .

التحديث من 04/29/2020 - أصبح من الواضح الآن أن منحنيات العدد اليومي للعدوى مختلفة تمامًا في بلدان مختلفة. ويبدو أنها تعتمد بشكل كبير على مدى الإصابة. من المرجح أن يكون المنحنى المثالي على شكل جرس على غرار كوريا الجنوبية استثناءً للقاعدة. الشكل الأكثر شيوعًا هو الزيادة الحادة إلى الذروة والانخفاض اللاحق الذي يمتد أكثر بمرور الوقت. لذلك ، في الواقع ، سيستمر انخفاض معدل الإصابة لفترة أطول من تلك التي توقعها هذا النموذج في أوائل أبريل.

دقيقة العناية UFO


COVID-19 — , SARS-CoV-2 (2019-nCoV). — , /, .



, .

, , .

: |


في البداية ، من أجل تقييم توقيت الوباء ، استخدمت لوحات المعلومات المتاحة للجمهور. كان أحد المواقع الأولى هو موقع مركز علوم وهندسة النظم بجامعة جونز هوبكنز.

صورة

إنه جميل للغاية ببساطته المشؤومة. حتى وقت قريب ، لم تسمح ببناء ديناميكيات زيادة العدوى بالأيام ، ولكن تم تصحيحها. ومن الغريب أنه يسمح لك بمشاهدة انتشار جائحة على خريطة العالم. نظرًا للتدرج اللوني الأسود والأحمر للوحة العدادات ، لا يوصى بمشاهدتها لفترة طويلة. أعتقد أن هذا قد يكون محفوفًا بحدوث نوبات من القلق تتحول إلى أشكال مختلفة من الذعر.

من أجل إبقاء إصبعي على النبض ، أحببت الصفحة حول COVID-19 أكثرعلى مورد Worldometer. يحتوي على معلومات عن البلدان في شكل جدول:

صورة

عندما تنقر على البلد المطلوب ، فإننا نقع في معلومات أكثر تفصيلاً حوله ، بما في ذلك المنحنيات اليومية والتراكمية للعدوى / المستعادة / الميتة.

هناك لوحات تحكم أخرى. على سبيل المثال ، للحصول على معلومات متعمقة حول بلدنا ، يمكنك ببساطة كتابة "COVID-19" في سطر بحث Yandex وستجد هذا:

صورة

حسنًا ، ربما سنتوقف عند هذا الحد. ليس في لوحات المعلومات الثلاث هذه ، ولا في عدة لوحات أخرى ، لم أتمكن من العثور على معلومات مع التوقعات عندما ينخفض ​​الوباء أخيرًا.

قليلا عن الرسوم البيانية


حاليًا ، تكتسب العدوى زخمًا فقط ، والأكثر إثارة للاهتمام هي الرسوم البيانية مع زيادة يومية في عدد الحالات. فيما يلي مثال للولايات المتحدة:

صورة

يمكن ملاحظة أن عدد المصابين يتزايد كل يوم. على مثل هذه الرسوم البيانية ، بالطبع ، نحن لا نتحدث عن جميع أولئك الذين أصيبوا بالعدوى (لا يمكن تحديد عددهم بدقة) ، ولكن فقط عن الحالات المؤكدة. ولكن للإيجاز ، فيما يلي سنطلق على هؤلاء المصابين "ببساطة" المصابين.

كيف يبدو الوباء المروض ؟ مثال هنا هو رسم بياني لكوريا الجنوبية:

صورة

يمكن ملاحظة أن الزيادة اليومية للمصابين نمت أولاً ، ثم وصلت إلى ذروتها ، وانخفضت وثبتت عند مستوى ثابت معين (حوالي 100 شخص في اليوم). هذا ليس انتصارًا كاملًا على الفيروس ، ولكنه نجاح كبير. سمح هذا للبلاد ببدء الاقتصاد (على الرغم من أنهم ، كما يقولون ، تمكن الكوريون من عدم إبطائه) والعودة إلى حياة أقل طبيعية.

يمكن افتراض أن الوضع في البلدان الأخرى سيتطور بطريقة مماثلة. أي أن النمو في المرحلة الأولى سيحل محله الاستقرار ، ومن ثم سينخفض ​​عدد المرضى كل يوم. والنتيجة هي منحنى على شكل جرس. دعونا نبحث عن قمم منحنيات أكثر البلدان "إصابة".

تنزيل البيانات ومعالجتها


يتم تحديث بيانات توزيع Coronavirus بشكل مستمر هنا . تحتوي جداول المصدر على منحنيات تراكمية ، ويمكن التقاطها ومعالجتها مسبقًا باستخدام برنامج نصي صغير.

مثله
import pandas as pd
import ipywidgets as widgets
from ipywidgets import interact
import matplotlib.pyplot as plt

pd.set_option('display.max_columns', None)

#  
url = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/'
confirmed = pd.read_csv(url + 'time_series_covid19_confirmed_global.csv', sep = ',')
deaths = pd.read_csv(url + 'time_series_covid19_deaths_global.csv', sep = ',')
recovered = pd.read_csv(url + 'time_series_covid19_recovered_global.csv', sep = ',')

#   -   'dd.mm.yy'
new_cols = list(confirmed.columns[:4]) + list(confirmed.columns[4:].map(lambda x: '{0:02d}.{1:02d}.{2:d}'.format(int(x.split(sep='/')[1]), int(x.split(sep='/')[0]), int(x.split(sep='/')[2]))))
confirmed.columns = new_cols
recovered.columns = new_cols
deaths.columns = new_cols

#     
confirmed_daily = confirmed.copy()
confirmed_daily.iloc[:,4:] = confirmed_daily.iloc[:,4:].diff(axis=1)
deaths_daily = deaths.copy()
deaths_daily.iloc[:,4:] = deaths_daily.iloc[:,4:].diff(axis=1)
recovered_daily = recovered.copy()
recovered_daily.iloc[:,4:] = recovered_daily.iloc[:,4:].diff(axis=1)

#       
smooth_conf_daily = confirmed_daily.copy()
smooth_conf_daily.iloc[:,4:] = smooth_conf_daily.iloc[:,4:].rolling(window=8, min_periods=2, center=True, axis=1).mean()
smooth_conf_daily.iloc[:,4:] = smooth_conf_daily.iloc[:,4:].round(1)

#   ,    
last_date = confirmed.columns[-1]

#  20       
confirmed_top = confirmed.iloc[:, [1, -1]].groupby('Country/Region').sum().sort_values(last_date, ascending = False).head(20)
countries = list(confirmed_top.index)

# ,      20 
conf_tot_ratio = confirmed_top.sum() / confirmed.iloc[:, 4:].sum()[-1]

#    
# countries.append('Russia')

#       ,   
l1 = 'Infected at ' + last_date + ' - ' + str(confirmed.iloc[:, 4:].sum()[-1])
l2 = 'Recovered at ' + last_date + ' - ' + str(recovered.iloc[:, 4:].sum()[-1])
l3 = 'Dead at ' + last_date + ' - ' + str(deaths.iloc[:, 4:].sum()[-1])

#      
fig, ax = plt.subplots(figsize = [16,6])
ax.plot(confirmed.iloc[:, 4:].sum(), '-', alpha = 0.6, color = 'orange', label = l1)
ax.plot(recovered.iloc[:, 4:].sum(), '-', alpha = 0.6, color = 'green', label = l2)
ax.plot(deaths.iloc[:, 4:].sum(), '-', alpha = 0.6, color = 'red', label = l3)

ax.legend(loc = 'upper left', prop=dict(size=12))
ax.xaxis.grid(which='minor')
ax.yaxis.grid()
ax.tick_params(axis = 'x', labelrotation = 90)
plt.title('COVID-19 in all countries. Top 20 countries consists {:.2%} of total confirmed infected cases.'.format(conf_tot_ratio[0]))
plt.show()


وبالتالي ، يمكنك الحصول على نفس المنحنيات الموجودة على لوحات المعلومات:

صورة

هناك القليل من الإضافات في البرنامج النصي غير مطلوب لعرض الرسم البياني ، ولكن ستكون هناك حاجة إليه في الخطوات التالية. على سبيل المثال ، قمت على الفور بتشكيل قائمة من 20 دولة مع الحد الأقصى لعدد المصابين اليوم. بالمناسبة - هذا هو 90 ٪ من جميع المصابين.

استمر. أرقام الزيادة اليومية في المرضى "صاخبة". لذلك ، سيكون من اللطيف تنعيم الرسم البياني. أضف خط اتجاه إلى الرسوم البيانية اليومية (استخدمت متوسط ​​متحرك مركزي). اتضح بطريقة أو بأخرى مثل هذا:

صورة

يظهر الاتجاه باللون الأسود. هذا منحنى سلس إلى حد ما مع ذروة واحدة. يبقى العثور على بداية تفشي المرض (السهم الأحمر) ووقوع الذروة (الأخضر). مع ذروة ، كل شيء بسيط - هذا هو الحد الأقصى للبيانات السلسة. علاوة على ذلك ، إذا كان الحد الأقصى يقع في أقصى يمين الرسم البياني ، فلن يتم تجاوز الذروة بعد. إذا بقي الحد الأقصى إلى اليسار - على الأرجح بقيت القمة في الماضي.

يمكن العثور على بداية الاندفاع بطرق مختلفة. لنفترض ببساطة أن هذه هي النقطة الزمنية التي يبدأ فيها عدد المصابين في اليوم في تجاوز 1٪ من الحد الأقصى لعدد المصابين في اليوم.

الرسم البياني متماثل تمامًا. أي أن المدة من بداية الوباء إلى الذروة تساوي تقريبًا المدة من الذروة إلى الانخفاض.وبالتالي ، إذا وجدنا عدد الأيام من البداية حتى الذروة ، فسيكون على نفس العدد تقريبًا من الأيام الانتظار حتى يهدأ الوباء .

سنضع كل هذا المنطق في النص التالي.

في مثل هذا
from datetime import timedelta, datetime

#     20  + .
confirmed_top = confirmed_top.rename(columns={str(last_date): 'total_confirmed'})
dates = [i for i in confirmed.columns[4:]]

for country in countries:
    
    #       ,      ,  
    confirmed_top.loc[country, 'total_confirmed'] = confirmed.loc[confirmed['Country/Region'] == country,:].sum()[4:][-1]
    confirmed_top.loc[country, 'last_day_conf'] = confirmed.loc[confirmed['Country/Region'] == country,:].sum()[-1] - confirmed.loc[confirmed['Country/Region'] == country,:].sum()[-2]
    confirmed_top.loc[country, 'mortality, %'] = round(deaths.loc[deaths['Country/Region'] == country,:].sum()[4:][-1]/confirmed.loc[confirmed['Country/Region'] == country,:].sum()[4:][-1]*100, 1)
    
    #       .
    smoothed_conf_max = round(smooth_conf_daily[smooth_conf_daily['Country/Region'] == country].iloc[:,4:].sum().max(), 2)
    peak_date = smooth_conf_daily[smooth_conf_daily['Country/Region'] == country].iloc[:,4:].sum().idxmax()
    peak_day = dates.index(peak_date)
    
    #      ,      1%    
    start_day = (smooth_conf_daily[smooth_conf_daily['Country/Region'] == country].iloc[:,4:].sum() < smoothed_conf_max/100).sum()
    start_date = dates[start_day-1]
    
    #     
    confirmed_top.loc[country, 'trend_max'] = smoothed_conf_max
    confirmed_top.loc[country, 'start_date'] = start_date
    confirmed_top.loc[country, 'peak_date'] = peak_date
    confirmed_top.loc[country, 'peak_passed'] = round(smooth_conf_daily.loc[smooth_conf_daily['Country/Region'] == country, last_date].sum(), 2) != smoothed_conf_max
    confirmed_top.loc[country, 'days_to_peak'] = peak_day - start_day
    
    #   ,    
    if confirmed_top.loc[country, 'peak_passed']:
         confirmed_top.loc[country, 'end_date'] = (datetime.strptime(confirmed_top.loc[country, 'peak_date']+'20', "%d.%m.%Y").date() + timedelta(confirmed_top.loc[country, 'days_to_peak'])).strftime('%d.%m.%Y')

#    
confirmed_top.loc['China', 'start_date'] = '22.01.20'
confirmed_top


في المخرج نحصل على مثل هذا الجدول لأفضل 20 دولة.

التحديث 10.04.2020: في وقت كتابة هذا التقرير ، لم تكن روسيا في المراكز العشرين الأولى ، لكنها ظهرت في 7 أبريل في المركز العشرين. غادر 10 أبريل في 18. يتضمن الجدول أيضًا مواعيد إجراءات الحجر الصحي في مختلف البلدان.

صورة

الأعمدة التالية في الجدول:
total_confertain - العدد الإجمالي للمصابين في البلد ؛
last_day_conf - عدد المصابين في اليوم الأخير ؛
معدل الوفيات ، النسبة المئوية - معدل الوفيات (عدد القتلى / عدد المصابين) ؛
trend_max - الاتجاه الأقصى ؛
start_date - تاريخ بدء الوباء في البلد ؛
أوقات الذروة - تاريخ الذروة ؛
الذروة - علم الذروة (إذا تم تمرير الذروة) ؛
days_to_peak - عدد الأيام التي مرت من البداية إلى الذروة ؛
end_date - تاريخ انتهاء الوباء.

التحديث 10.04.2020: تم الوصول إلى ذروة الإصابة في 14 دولة من أصل 20. علاوة على ذلك ، في المتوسط ​​، من بداية العدوى الجماعية إلى الذروة ، يستغرق الأمر 25 يومًا في المتوسط:

صورة

وفقًا للمنطق أعلاه ، بحلول نهاية أبريل ، سيتعين على الوضع التطبيع في جميع البلدان قيد النظر تقريبًا . كما سيكون ، سيخبرنا الوقت فقط.

التحديث 10.04.2020: يمكنك أن ترى أن الرسوم البيانية للدول الأوروبية ، على عكس الرسم البياني لكوريا الجنوبية ، لديها ركود أكثر رقة بعد الذروة.

هناك أيضًا نص برمجي يسمح لك بعرض الرسوم البيانية لكل بلد.

هذه
@interact
def plot_by_country(country = countries):
    
    #   
    l1 = 'Infected at ' + last_date + ' - ' + str(confirmed.loc[confirmed['Country/Region'] == country,:].sum()[-1])
    l2 = 'Recovered at ' + last_date + ' - ' + str(recovered.loc[recovered['Country/Region'] == country,:].sum()[-1])
    l3 = 'Dead at ' + last_date + ' - ' + str(deaths.loc[deaths['Country/Region'] == country,:].sum()[-1])
    
    #        
    df = pd.DataFrame(confirmed_daily.loc[confirmed_daily['Country/Region'] == country,:].sum()[4:])
    df.columns = ['confirmed_daily']
    df['recovered_daily'] = recovered_daily.loc[recovered_daily['Country/Region'] == country,:].sum()[4:]
    df['deaths_daily'] = deaths_daily.loc[deaths_daily['Country/Region'] == country,:].sum()[4:]
    df['deaths_daily'] = deaths_daily.loc[deaths_daily['Country/Region'] == country,:].sum()[4:]
    df['smooth_conf_daily'] = smooth_conf_daily.loc[smooth_conf_daily['Country/Region'] == country,:].sum()[4:]
    
    #  
    fig, ax = plt.subplots(figsize = [16,6], nrows = 1)
    plt.title('COVID-19 dinamics daily in ' + country)
    
    #      ,   
    ax.bar(df.index, df.confirmed_daily, alpha = 0.5, color = 'orange', label = l1)
    ax.bar(df.index, df.recovered_daily, alpha = 0.6, color = 'green', label = l2)
    ax.bar(df.index, df.deaths_daily, alpha = 0.7, color = 'red', label = l3)
    ax.plot(df.index, df.smooth_conf_daily, alpha = 0.7, color = 'black')
    
    #     .
    start_date = confirmed_top[confirmed_top.index == country].start_date.iloc[0]
    start_point = smooth_conf_daily.loc[smooth_conf_daily['Country/Region'] == country, start_date].sum()
    ax.plot_date(start_date, start_point, 'o', alpha = 0.7, color = 'black')
    shift = confirmed_top.loc[confirmed_top.index == country, 'trend_max'].iloc[0]/40
    plt.text(start_date, start_point + shift, 'Start at ' + start_date, ha ='right', fontsize = 20)
    
    peak_date = confirmed_top[confirmed_top.index == country].peak_date.iloc[0]
    peak_point = smooth_conf_daily.loc[smooth_conf_daily['Country/Region'] == country, peak_date].sum()
    ax.plot_date(peak_date, peak_point, 'o', alpha = 0.7, color = 'black')
    plt.text(peak_date, peak_point + shift, 'Peak at ' + peak_date, ha ='right', fontsize = 20)
    
    ax.xaxis.grid(False)
    ax.yaxis.grid(False)
    ax.tick_params(axis = 'x', labelrotation = 90)
    ax.legend(loc = 'upper left', prop=dict(size=12))
    
    #         .
    max_pos = max(df['confirmed_daily'].max(), df['recovered_daily'].max())
    if confirmed_top[confirmed_top.index == country].peak_passed.iloc[0]:
        estimation = 'peak is passed - end of infection ' + confirmed_top[confirmed_top.index == country].end_date.iloc[0]
    else:
        estimation = 'peak is not passed - end of infection is not clear'
    plt.text(df.index[len(df.index)//2], 3*max_pos//4, country, ha ='center', fontsize = 50)
    plt.text(df.index[len(df.index)//2], 2*max_pos//3, estimation, ha ='center', fontsize = 20)
    
    #plt.savefig(country + '.png', bbox_inches='tight', dpi = 75)
    plt.show()


فيما يلي الوضع الحالي في روسيا (تحديث 04/10/2020):

صورة

لسوء الحظ ، لم يتم تجاوز الذروة حتى الآن ، لذلك من الصعب عمل تنبؤات بشأن توقيت انخفاض الحدوث. ولكن بالنظر إلى أن التفشي يستمر لمدة 26 يومًا ، يمكننا أن نتوقع أننا خلال الأسبوع سنرى ذروة وسيبدأ معدل الإصابة في الانخفاض. أود أن أجرؤ على اقتراح أنه في أوائل شهر مايو كان الوضع طبيعيًا (كنت دائمًا متفائلًا ، يجب أن أقول).

شكرا جزيلا على القراءة حتى النهاية. كن بصحة جيدة وستكون القوة معنا. فيما يلي رسوم بيانية لبقية الدول العشرين بترتيب تنازلي لعدد المصابين. إذا كنت بحاجة إلى المزيد من البيانات الحديثة - يمكنك تشغيل البرامج النصية الواردة في النص ، سيتم إعادة حساب كل شيء للتاريخ الحالي.

التحديث 10.04.2020 - يتم تحديث الرسومات.

الولايات المتحدة الأمريكية
image

إسبانيا
image

إيطاليا
image

ألمانيا
image

فرنسا
image

الصين
image

إيران
image

المملكة المتحدة
image

ديك رومي
image

سويسرا
image

بلجيكا
image

هولندا
image

كندا
image

النمسا
image

البرتغال
image

البرازيل
image

كوريا الجنوبية
image

إسرائيل
image

السويد
image

النرويج
image

All Articles