今年2020剛開始便被這個來自2019年傳出的2019n-Cov(俗稱的武漢肺炎病毒)鬧的人心惶惶,而在我們偉大的中國共產黨領導下,疫情也是如雨後春筍般的在中國甚至鄰近國家散播,而前陣子有個同學在偉大中國共產黨疫情通報網(link: http://www.nhc.gov.cn/xcs/yqtb/list_gzbd.shtml) 上,將疫情人數的數量做成表,並用excel繪製了一個簡單的圖表以及用Benford’s law檢查了資料是否有造假的可能,但因疫情假期還很長,因此變跟他要了這個(基本上是造假的)data,想說跑一些簡單的資料探勘看看會不會有有趣的結果。

1. 資料探勘

讀取資料

import pandas as pd
import numpy as np

df = pd.read_csv('C:/Users/User/OneDrive - student.nsysu.edu.tw/Documents/Python/ML/2019nCov/2019nCov.csv')

計算每日成長人數

成長人數 = [0]
for i in range(len(df)-1):
    成長人數 += [df['確診'][i+1]-df['確診'][i]]
df['確診成長人數'] = 成長人數
df
日期 確診 死亡 治癒 確診成長率 死亡率 治癒率 確診成長人數
0 1月11日 41 1 2 NaN 0.024390 0.048780 0
1 1月12日 41 1 6 0.000000 0.024390 0.146341 0
2 1月13日 41 1 7 0.000000 0.024390 0.170732 0
3 1月14日 41 1 7 0.000000 0.024390 0.170732 0
4 1月15日 41 1 7 0.000000 0.024390 0.170732 0
5 1月16日 41 2 12 0.000000 0.048780 0.292683 0
6 1月17日 45 2 15 0.097561 0.044444 0.333333 4
7 1月18日 62 2 19 0.377778 0.032258 0.306452 17
8 1月19日 121 3 24 0.951613 0.024793 0.198347 59
9 1月20日 198 3 25 0.636364 0.015152 0.126263 77
10 1月21日 291 3 25 0.469697 0.010309 0.085911 93
11 1月22日 440 9 25 0.512027 0.020455 0.056818 149
12 1月23日 571 17 25 0.297727 0.029772 0.043783 131
13 1月24日 830 25 34 0.453590 0.030120 0.040964 259
14 1月25日 1287 41 38 0.550602 0.031857 0.029526 457
15 1月26日 1975 56 49 0.534577 0.028354 0.024810 688
16 1月27日 2744 80 51 0.389367 0.029155 0.018586 769
17 1月28日 4515 106 60 0.645408 0.023477 0.013289 1771
18 1月29日 5974 132 103 0.323145 0.022096 0.017241 1459
19 1月30日 7711 170 124 0.290760 0.022046 0.016081 1737
20 1月31日 9692 213 171 0.256906 0.021977 0.017643 1981
21 2月1日 11791 259 243 0.216570 0.021966 0.020609 2099
22 2月2日 14380 304 328 0.219574 0.021140 0.022809 2589
23 2月3日 17205 361 475 0.196453 0.020982 0.027608 2825
24 2月4日 20438 425 632 0.187910 0.020795 0.030923 3233
25 2月5日 24324 490 892 0.190136 0.020145 0.036672 3886
26 2月6日 28018 563 1153 0.151866 0.020094 0.041152 3694
27 2月7日 31161 636 1540 0.112178 0.020410 0.049421 3143
28 2月8日 34546 722 2050 0.108629 0.020900 0.059341 3385
29 2月9日 37198 811 2649 0.076767 0.021802 0.071214 2652
30 2月10日 40171 903 3281 0.079924 0.022479 0.081676 2973
31 2月11日 42638 1016 3996 0.061412 0.023829 0.093719 2467
32 2月12日 44653 1113 4740 0.047258 0.024926 0.106152 2015
33 2月13日 59868 1367 5911 0.340739 0.022834 0.098734 15215

畫每日確診人數圖

import matplotlib.pyplot as plt
x = df.iloc[:,1:2]

plt.plot(x)
plt.xlabel("Date")
plt.ylabel("Number of people")
plt.title("Wuhan Pneumonia Cumulative Amount Plot")

plt.show()

畫每日肺炎成長率

y = df.iloc[:,4:5]

plt.plot(y)
plt.xlabel("Date")
plt.ylabel("Infected Growth Rate")
plt.title("Wuhan Pneumonia Growth Rate Plot")

plt.show()

計算各項平均數值

print('平均確診成長率:',np.mean(df['確診成長率']))
print('平均死亡率:',np.mean(df['死亡率']))
print('平均治癒率:',np.mean(df['治癒率']))
print('平均確診成長人數:',np.mean(df['確診成長人數']))

平均確診成長率: 0.2659557775454546
平均死亡率: 0.024685260176470585
平均治癒率: 0.09026695652941175
平均確診成長人數: 1759.6176470588234

從數據上來看,死亡率確實很精準地落在百分之二左右,而成長人數因中共的確診方式在2/13時宣稱,因序列檢驗耗時太久,因此只要符合病徵以及MRI確認肺部有發炎症狀即確診,因此人數突然飆升。

2. The SIR epidemic model

一年級有在統計模擬課程上稍微使用過SIR Model,因此這次利用前面的平均數,建立簡單的模擬模型,模擬感染平均狀況的每日人數變化。
這裡僅利用武漢的人口總數計算,因應中國當局以城市當作封閉單位,因此以一個單位內部傳染情況來做推算。
因此利用:
總人口數:\(N\) = 10000000、
平均移除率(平均死亡率+平均治癒率):\(\gamma\) = 0.024685260176470585+0.09026695652941175 = 0.11495221670588233 假設感染接觸率:\(\beta\) = 0.9、0.6、0.25

這裡假設幾種感染接觸率,這裡的接觸率我們假設三種情況,人口正常移動且無防護意識:0.9、人口減少移動且少部分有防疫意識:0.6、人口低流動且盡可能不接觸可能的感染者:0.25。

Type 1:人口正常移動且無防護意識

import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt

# Total population, N.
N = 100000000
# Initial number of infected and recovered individuals, I0 and R0.
I0, R0 = 1, 0
# Everyone else, S0, is susceptible to infection initially.
S0 = N - I0 - R0
# Contact rate, beta, and mean recovery rate, gamma, (in 1/days).
beta, gamma = 0.9, 0.11495221670588233
# A grid of time points (in days)
t = np.linspace(0, 160, 160)

# The SIR model differential equations.
def deriv(y, t, N, beta, gamma):
    S, I, R = y
    dSdt = -beta * S * I / N
    dIdt = beta * S * I / N - gamma * I
    dRdt = gamma * I
    return dSdt, dIdt, dRdt

# Initial conditions vector
y0 = S0, I0, R0
# Integrate the SIR equations over the time grid, t.
ret = odeint(deriv, y0, t, args=(N, beta, gamma))
S, I, R = ret.T

# Plot the data on three separate curves for S(t), I(t) and R(t)
fig = plt.figure(facecolor='w')
ax = fig.add_subplot(111)
ax.plot(t, S/100000000, 'b', alpha=0.5, lw=2, label='Susceptible')
ax.plot(t, I/100000000, 'r', alpha=0.5, lw=2, label='Infected')
ax.plot(t, R/100000000, 'g', alpha=0.5, lw=2, label='Recovered with immunity')
ax.set_xlabel('Time /days')
ax.set_ylabel('Number (10000000s)')
#ax.set_ylim(0,1.2)
ax.yaxis.set_tick_params(length=0)
ax.xaxis.set_tick_params(length=0)
ax.grid(b=True, which='major', c='w', lw=2, ls='-')
legend = ax.legend()
legend.get_frame().set_alpha(0.5)
for spine in ('top', 'right', 'bottom', 'left'):
    ax.spines[spine].set_visible(False)
plt.show()

從上圖表可以看出,若對此病毒無任何作為時,可以在近一個月的時間將整個城市的人全面感染。

Type 2:人口減少移動且少部分有防疫意識

beta = 0.5
# Integrate the SIR equations over the time grid, t.
ret = odeint(deriv, y0, t, args=(N, beta, gamma))
S, I, R = ret.T
# Plot the data on three separate curves for S(t), I(t) and R(t)
fig = plt.figure(facecolor='w')
ax = fig.add_subplot(111)
ax.plot(t, S/100000000, 'b', alpha=0.5, lw=2, label='Susceptible')
ax.plot(t, I/100000000, 'r', alpha=0.5, lw=2, label='Infected')
ax.plot(t, R/100000000, 'g', alpha=0.5, lw=2, label='Recovered with immunity')
ax.set_xlabel('Time /days')
ax.set_ylabel('Number (10000000s)')
#ax.set_ylim(0,1.2)
ax.yaxis.set_tick_params(length=0)
ax.xaxis.set_tick_params(length=0)
ax.grid(b=True, which='major', c='w', lw=2, ls='-')
legend = ax.legend()
legend.get_frame().set_alpha(0.5)
for spine in ('top', 'right', 'bottom', 'left'):
    ax.spines[spine].set_visible(False)
plt.show()

在減少人口流動後,全面感染的時間將被拉長至兩個月,將有助於爭取疫苗或是特效藥的研發時間。

Type 3:人口低流動且盡可能不接觸可能的感染者

beta = 0.25
# Integrate the SIR equations over the time grid, t.
ret = odeint(deriv, y0, t, args=(N, beta, gamma))
S, I, R = ret.T
# Plot the data on three separate curves for S(t), I(t) and R(t)
fig = plt.figure(facecolor='w')
ax = fig.add_subplot(111)
ax.plot(t, S/100000000, 'b', alpha=0.5, lw=2, label='Susceptible')
ax.plot(t, I/100000000, 'r', alpha=0.5, lw=2, label='Infected')
ax.plot(t, R/100000000, 'g', alpha=0.5, lw=2, label='Recovered with immunity')
ax.set_xlabel('Time /days')
ax.set_ylabel('Number (10000000s)')
#ax.set_ylim(0,1.2)
ax.yaxis.set_tick_params(length=0)
ax.xaxis.set_tick_params(length=0)
ax.grid(b=True, which='major', c='w', lw=2, ls='-')
legend = ax.legend()
legend.get_frame().set_alpha(0.5)
for spine in ('top', 'right', 'bottom', 'left'):
    ax.spines[spine].set_visible(False)
plt.show()

在具備有良好的全面控制下,將可有效的避免病毒的傳播 ,因此若要減緩甚至是阻止病毒的傳播,減少人口的接觸率將會是最直接最簡單的方式。

3. Benford’s Law

這裡我們來檢查一下偉大黨提供的數據是否有造假的疑慮,以下是excle上面執行的結果截圖:

數字4出現的次數顯得有點突出,若是數據造假,落在數字4難道真的巧合嗎?不,我不這麼認為。
人口清洗的陰謀論、數字6之後出現的次數也相同,難道這是防疫中心想要表達64 64的訊息給廣大的萬萬子民嗎?

總之,希望這次疫情能夠順利結束,大家也能夠配合政府政策,減緩並阻止病毒的擴張,Peace!