By: Fabio Pinto
(Susceptibles, expuestos, infectados, recuperados)
En una población de tamaño fijo N en la que se ha desatado una epidemia que se propaga mediante contagio, en un tiempo t los individuos pueden estar en tres estados distintos:
- susceptibles S(t),
- infectados I(t),
- recuperados R(t)
- Qianying Lin, Shi Zhao, Daozhou Gao, Yijun Lou, Shu Yang, Salihu S. Musa, Maggie H. Wang, Yongli Cai, Weiming Wang, Lin Yang, Daihai He, A conceptual model for the coronavirus disease 2019 (COVID-19) outbreak in Wuhan, China with individual reaction and governmental action, International Journal of Infectious Diseases 93 (2020), 211–216. Publicado: March 04, 2020. https://www.ijidonline.com/article/S1201-9712(20)30117-X/fulltext
- Gutierrez and Varona, 2020. Universidad De La Rioja. [online] Análisis de la posible evolución de la epidemia de coronavirus COVID-19 por medio de un modelo SEIR. Publicado: March 15, 2020. https://www.unirioja.es/apnoticias/servlet/Archivo?C_BINARIO=12051 [Accessed 13 April 2020].
from IPython.display import Image Image(filename='data/sir.png')
Image(filename='data/seir.png')
from IPython.display import Image Image(filename='data/edosir.png')
In [26]:
Image(filename='data/edoseir.png')
- Beta: Tasa de infeccion
- Gamma: Tasa de recuperación
- Ommega: Tasa de incubación
import scipy.integrate as spi import numpy as np import matplotlib.pyplot as plt import pandas as pd
In [28]:
## Definimos las ecuaciones diferenciales del modelo def odeSIR(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
def odeSEIR(y, t, N, beta, gamma, omega): S, E, I, R = y dSdt = -beta * S * I / N dEdt = beta * S * I / N - omega*E dIdt = omega*E - gamma * I dRdt = gamma * I return dSdt, dEdt, dIdt, dRdt
In [30]:
def modeloSIR(N, beta, gamma, days): I0, R0 = 1, 0 ## S susceptibles S0 = N - I0 - R0 ## beta = ratio de contacto entre personas ## gamma = inverso del tiempo de recuperación # Vector de tiempo t = range(0,days) # Vector de condiciones iniciales y0 = S0, I0, R0 # Evaluación del sistema de ecuaciones diferenciales ret = spi.odeint(odeSIR, y0, t, args=(N, beta, gamma)) S, I, R = ret.T return S, I, R
Modelado y simulación del modelo SEIR
In [31]:
def modeloSEIR(N, beta, gamma, omega, days): """N = población total """ I0, R0, E0 = 1, 0, 0 ## S susceptibles S0 = N - I0 - R0- E0 ## beta = ratio de contacto entre personas ## gamma = inverso del tiempo de recuperación ## omega = tasa de incubación # Vector de tiempo t = range(0,days) # Vector de condiciones iniciales y0 = S0, E0,I0, R0 # Evaluación del sistema de ecuaciones diferenciales ret = spi.odeint(odeSEIR, y0, t, args=(N, beta, gamma, omega)) S, E, I, R = ret.T return S, E, I, R
In [32]:
def informeSIR(d): mean = int(np.mean(d)) maxx = int(np.max(d)) max_day = d.argmax() print('Promedio Diario = ' + str(mean)) print('Máxima tasa = ' + str(maxx)) print('Dia del pico = ' + str(max_day))
'Aplanar la curva': Modelo SIR con diferentes medidas de contención
La presencia o no de medidas de contención (aislamiento, cuarentena, etc) determinan la variación de la tasa de contagio
Para el ejemplo estamos tomando un beta de 2.5 inicial para ausencia de medidas de contención y 0.5 para medidas de contención serias.
S_1, I_1, R_1 = modeloSIR(1e5,2.5,1/5,100) # sin ninguna medida de contención S_2, I_2, R_2 = modeloSIR(1e5,1.5,1/5,100) # con medidas de contención leves S_3, I_3, R_3 = modeloSIR(1e5,0.5,1/5,100) # con medidas de contención fuertes
t = range(0,len(S_1)) plt.subplots(figsize=(10, 10)) plt.subplot(311) plt.plot(t, S_1, 'g', label = 'Susceptibles') plt.plot(t, I_1, 'r', label = 'Infectados') plt.plot(t, R_1, 'b', label = 'Recuperados') plt.ylabel('Conteo') plt.title('Modelo SIR con beta = 2.5') plt.legend() plt.subplot(312) plt.plot(t, S_2, 'g', label = 'Susceptibles') plt.plot(t, I_2, 'r', label = 'Infectados') plt.plot(t, R_2, 'b', label = 'Recuperados') plt.ylabel('Conteo') plt.title('Modelo SIR con beta = 1.5') plt.legend() plt.subplot(313) plt.plot(t, S_3, 'g', label = 'Susceptibles') plt.plot(t, I_3, 'r', label = 'Infectados') plt.plot(t, R_3, 'b', label = 'Recuperados') plt.xlabel('Dias') plt.ylabel('Conteo') plt.title('Modelo SIR con beta = 0.5') plt.legend()
<matplotlib.legend.Legend at 0x108d9f71ac8>
In [39]:
t = range(0,len(I_1)) plt.plot(t, I_1, 'g', label = 'Infectados sin medidas') plt.plot(t, I_2, 'r', label = 'Infectados con medidas leves') plt.plot(t, I_3, 'b', label = 'Infectados con medidas serias') plt.legend() plt.show()
In [40]:
print("---------Infectados sin medidas-----------") informeSIR(I_1) print("---------Infectados con medidas leves-----------") informeSIR(I_2) print("---------Infectados con medidas serias-----------") informeSIR(I_3) ---------Infectados sin medidas----------- Promedio Diario = 5000 Máxima tasa = 71489 Dia del pico = 6 ---------Infectados con medidas leves----------- Promedio Diario = 4997 Máxima tasa = 58608 Dia del pico = 10 ---------Infectados con medidas serias----------- Promedio Diario = 4462 Máxima tasa = 23330 Dia del pico = 40
In [41]:
t = range(0,len(I_1)) plt.plot(t, R_1, 'g', label = 'Recuperados sin medidas') plt.plot(t, R_2, 'r', label = 'Recuperados con medidas leves') plt.plot(t, R_3, 'b', label = 'Recuperados con medidas serias') plt.legend() plt.show()
In [42]:
t = range(0,len(S_1)) plt.plot(t, S_1, 'g', label = 'Susceptibles sin medidas') plt.plot(t, S_2, 'r', label = 'Susceptibles con medidas leves') plt.plot(t, S_3, 'b', label = 'Susceptibles con medidas serias') plt.legend() plt.show()
'Aplanar la curva': Modelo SEIR con diferentes medidas de contención
S1, E1, I1, R1 = modeloSEIR(1e5,2.5,1/5,1/7,200) # sin ninguna medida de contención S2, E2, I2, R2 = modeloSEIR(1e5,1.5,1/5,1/7,200) # con medidas de contención leves S3, E3, I3, R3 = modeloSEIR(1e5,0.5,1/5,1/7,200) # con medidas de contención fuertes
t = range(0,len(S1)) plt.subplots(figsize=(10, 10)) plt.subplot(311) plt.plot(t, S1, 'g', label = 'Susceptibles') plt.plot(t, E1, 'c', label = 'Expuestos') plt.plot(t, I1, 'r', label = 'Infectados') plt.plot(t, R1, 'b', label = 'Recuperados') plt.ylabel('Conteo') plt.title('Modelo SIR con beta = 2.5') plt.legend() plt.subplot(312) plt.plot(t, S2, 'g', label = 'Susceptibles') plt.plot(t, E2, 'c', label = 'Expuestos') plt.plot(t, I2, 'r', label = 'Infectados') plt.plot(t, R2, 'b', label = 'Recuperados') plt.ylabel('Conteo') plt.title('Modelo SIR con beta = 1.5') plt.legend() plt.subplot(313) plt.plot(t, S3, 'g', label = 'Susceptibles') plt.plot(t, E3, 'c', label = 'Expuestos') plt.plot(t, I3, 'r', label = 'Infectados') plt.plot(t, R3, 'b', label = 'Recuperados') plt.xlabel('Dias') plt.ylabel('Conteo') plt.title('Modelo SIR con beta = 0.5') plt.legend()
<matplotlib.legend.Legend at 0x108d842ec48>
print("---------Infectados sin medidas-----------") informeSIR(I1) print("---------Infectados con medidas leves-----------") informeSIR(I2) print("---------Infectados con medidas serias-----------") informeSIR(I3)
---------Infectados sin medidas----------- Promedio Diario = 2499 Máxima tasa = 26478 Dia del pico = 31 ---------Infectados con medidas leves----------- Promedio Diario = 2498 Máxima tasa = 23033 Dia del pico = 44 ---------Infectados con medidas serias----------- Promedio Diario = 2227 Máxima tasa = 9578 Dia del pico = 119
print("---------Expuestos sin medidas-----------") informeSIR(E1) print("---------Expuestos con medidas leves-----------") informeSIR(E2) print("---------Expuestos con medidas serias-----------") informeSIR(E3)
---------Expuestos sin medidas----------- Promedio Diario = 3499 Máxima tasa = 49266 Dia del pico = 28 ---------Expuestos con medidas leves----------- Promedio Diario = 3498 Máxima tasa = 39267 Dia del pico = 40 ---------Expuestos con medidas serias----------- Promedio Diario = 3121 Máxima tasa = 14002 Dia del pico = 114
t = range(0,len(I1)) plt.plot(t, I1, 'g', label = 'Infectados sin medidas') plt.plot(t, I2, 'r', label = 'Infectados con medidas leves') plt.plot(t, I3, 'b', label = 'Infectados con medidas serias') plt.legend() plt.show()
t = range(0,len(S1)) plt.plot(t, S1, 'g', label = 'Susceptibles sin medidas') plt.plot(t, S2, 'r', label = 'Susceptibles con medidas leves') plt.plot(t, S3, 'b', label = 'Susceptibles con medidas serias') plt.legend() plt.show()