Análisis de Reinfección por COVID-19 y Factores de Salud. 🦠¶

Introducción y Planteamiento del Problema.¶

Este proyecto tiene como objetivo principal identificar y analizar los patrones y factores de riesgo asociados a la reinfección por COVID-19 utilizando el "COVID-19 Reinfection and Health Dataset" de Kaggle. 📊

Para lograr este objetivo, buscaremos responder las siguientes preguntas clave❓:

  • 1. Demografía de la Reinfección: ¿Existen diferencias significativas en la tasa de reinfección entre distintos grupos demográficos (edad, género)?
  • 2. Comorbilidades y Reinfección: ¿Qué condiciones de salud preexistentes (comorbilidades) están más fuertemente asociadas con un mayor riesgo de reinfección?
  • 3. Gravedad y Reinfección: ¿Hay una relación entre la gravedad de la infección inicial o la reinfección y los factores de salud del paciente?

Los hallazgos de este análisis podrían proporcionar información valiosa para:

  • Identificar grupos de población de alto riesgo.
  • Informar políticas de salud pública y recomendaciones de cuidados.
  • Guiar futuras investigaciones médicas sobre la inmunidad y el COVID-19.

Limitaciones Anticipadas: Se prevé que el dataset contenga un número significativo de valores faltantes, particularmente en las columnas de fecha, lo que requerirá una limpieza de datos cuidadosa y podría limitar ciertas líneas de análisis temporal.⏱️

1. Comenzar a importar librerías necesarias para limpieza de datos y su manipulación.📚¶

  • Pandas (como pd): Esta es la librería más crucial para la manipulación y el análisis de datos en Python.
  • Matplotlib.pyplot (como plt): La base para la creación de gráficos.
In [15]:
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.ticker import PercentFormatter
import plotly.express as px
import seaborn as sns

2. Carga e Inspección Preliminar del Dataset. 📊¶

En esta sección, cargaremos el dataset principal desde la carpeta data. A continuación, realizaremos una inspección inicial de los datos para comprender su estructura, tipos de variables y la presencia de valores faltantes. Este paso es fundamental para identificar los desafíos de limpieza de datos y planificar las transformaciones necesarias antes del análisis.

In [16]:
ruta_csv = '../data/covid.csv' #Definimos una variable que hace referencia a la ruta de nuestro csv
df = pd.read_csv(ruta_csv) #creamos un dataframe que va a leer los datos de nuestro csv
print('DataSet cargado correctamente') #si se cargo correcto, imprimimos un mensaje que lo haga saber
DataSet cargado correctamente
In [17]:
print('Vista de las 5 filas iniciales: ')
print(df.head()) # esta linea ayuda a cargar los primeros 5 elementos de nuestro dataset
print('\n Información de nuestro DataFrame: ')
df.info() #mostrara info general
print('\n Dimensiones de nuestro DataFrame: ')
print(df.shape) #mostrara filas x columnas
print('\n Estadisticas descriptiivas de columnas tipo int: ')
print(df.describe()) #datos numericos como mediana, min de nuestro dataframe
print('\n Valores nulos por columna: ')
print(df.isnull().sum()) #datos nulos 
Vista de las 5 filas iniciales: 
   Patient_ID  Age  Gender       Region Preexisting_Condition  \
0           1   69    Male  Hovedstaden               Obesity   
1           2   38    Male     Sjælland                Asthma   
2           3   41  Female   Syddanmark          Hypertension   
3           4   81  Female  Hovedstaden                Asthma   
4           5   50  Female   Syddanmark        Cardiovascular   

  Date_of_Infection COVID_Strain Symptoms  Severity Hospitalized  ...  \
0        2022-06-21        Delta     Mild  Moderate          Yes  ...   
1        2024-02-02      XBB.1.5     Mild  Moderate           No  ...   
2        2023-05-28         Beta     Mild      High          Yes  ...   
3        2023-08-13        Delta   Severe      High           No  ...   
4        2023-03-10        Delta     Mild      High           No  ...   

  Reinfection Date_of_Reinfection Vaccination_Status Vaccine_Type  \
0          No                 NaN                Yes          NaN   
1          No                 NaN                 No          NaN   
2          No                 NaN                Yes      Janssen   
3         Yes          2024-08-24                Yes  AstraZeneca   
4          No                 NaN                Yes          NaN   

  Doses_Received Date_of_Last_Dose Long_COVID_Symptoms     Occupation  \
0              1        2022-09-22                 NaN     Healthcare   
1              0               NaN                 NaN     Healthcare   
2              3        2024-05-14                 NaN     Unemployed   
3              1        2024-10-31                 NaN  Office Worker   
4              2        2023-07-05                 NaN        Student   

  Smoking_Status   BMI  
0          Never  27.7  
1          Never  21.9  
2          Never  22.7  
3          Never  27.7  
4          Never  11.9  

[5 rows x 26 columns]

 Información de nuestro DataFrame: 
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3000 entries, 0 to 2999
Data columns (total 26 columns):
 #   Column                   Non-Null Count  Dtype  
---  ------                   --------------  -----  
 0   Patient_ID               3000 non-null   int64  
 1   Age                      3000 non-null   int64  
 2   Gender                   3000 non-null   object 
 3   Region                   3000 non-null   object 
 4   Preexisting_Condition    2531 non-null   object 
 5   Date_of_Infection        3000 non-null   object 
 6   COVID_Strain             3000 non-null   object 
 7   Symptoms                 3000 non-null   object 
 8   Severity                 3000 non-null   object 
 9   Hospitalized             3000 non-null   object 
 10  Hospital_Admission_Date  876 non-null    object 
 11  Hospital_Discharge_Date  876 non-null    object 
 12  ICU_Admission            3000 non-null   object 
 13  Ventilator_Support       3000 non-null   object 
 14  Recovered                3000 non-null   object 
 15  Date_of_Recovery         1508 non-null   object 
 16  Reinfection              3000 non-null   object 
 17  Date_of_Reinfection      285 non-null    object 
 18  Vaccination_Status       3000 non-null   object 
 19  Vaccine_Type             1191 non-null   object 
 20  Doses_Received           3000 non-null   int64  
 21  Date_of_Last_Dose        1472 non-null   object 
 22  Long_COVID_Symptoms      220 non-null    object 
 23  Occupation               3000 non-null   object 
 24  Smoking_Status           3000 non-null   object 
 25  BMI                      3000 non-null   float64
dtypes: float64(1), int64(3), object(22)
memory usage: 609.5+ KB

 Dimensiones de nuestro DataFrame: 
(3000, 26)

 Estadisticas descriptiivas de columnas tipo int: 
        Patient_ID          Age  Doses_Received          BMI
count  3000.000000  3000.000000     3000.000000  3000.000000
mean   1500.500000    53.944000        0.981667    25.096500
std     866.169729    20.872919        1.154025     4.898435
min       1.000000    18.000000        0.000000    10.200000
25%     750.750000    36.000000        0.000000    21.800000
50%    1500.500000    54.000000        0.000000    25.100000
75%    2250.250000    72.000000        2.000000    28.500000
max    3000.000000    89.000000        3.000000    44.600000

 Valores nulos por columna: 
Patient_ID                    0
Age                           0
Gender                        0
Region                        0
Preexisting_Condition       469
Date_of_Infection             0
COVID_Strain                  0
Symptoms                      0
Severity                      0
Hospitalized                  0
Hospital_Admission_Date    2124
Hospital_Discharge_Date    2124
ICU_Admission                 0
Ventilator_Support            0
Recovered                     0
Date_of_Recovery           1492
Reinfection                   0
Date_of_Reinfection        2715
Vaccination_Status            0
Vaccine_Type               1809
Doses_Received                0
Date_of_Last_Dose          1528
Long_COVID_Symptoms        2780
Occupation                    0
Smoking_Status                0
BMI                           0
dtype: int64

3. Limpieza y Preprocesamiento de Datos. 🧼¶

Este es uno de los pasos más críticos en cualquier proyecto de análisis de datos. Los datos rara vez vienen en un formato perfecto para el análisis. Basándonos en la inspección anterior, necesitamos transformar y limpiar el dataset para asegurarnos de que sea preciso, consistente y esté en el formato correcto para responder a nuestras preguntas de investigación.

En este punto, nos enfocaremos en asegurar la calidad y consistencia del dataset para el análisis. Realizaremos los siguientes pasos:

  • Identificación y Eliminación de Duplicados: Para garantizar que cada entrada represente un paciente único y evitar sesgos en el análisis.
  • Ajuste de Nombres de Columnas: Renombraremos las columnas si sus nombres actuales no son claros, consistentes o legibles, facilitando su manipulación.
  • Conversión de Tipos de Datos: Corregiremos los tipos de datos de cada columna (ej., convertir fechas a datetime, textos a category o boolean, y asegurar tipos numéricos correctos) para permitir operaciones y análisis precisos.
  • Manejo Estratégico de Valores Nulos: Abordaremos los valores faltantes, incluyendo la creación de variables flag para nulos semánticos (como la ausencia de una fecha de evento) y la imputación o eliminación de otros nulos, para evitar sesgos y asegurar la integridad de las conclusiones.
In [18]:
df_limpio = df.copy() #creamos una copia del dataframe original
In [19]:
df_limpio.head() #mostramos las primeras 5 filas para verificar que se cargo el dataframe a limpiar
Out[19]:
Patient_ID Age Gender Region Preexisting_Condition Date_of_Infection COVID_Strain Symptoms Severity Hospitalized ... Reinfection Date_of_Reinfection Vaccination_Status Vaccine_Type Doses_Received Date_of_Last_Dose Long_COVID_Symptoms Occupation Smoking_Status BMI
0 1 69 Male Hovedstaden Obesity 2022-06-21 Delta Mild Moderate Yes ... No NaN Yes NaN 1 2022-09-22 NaN Healthcare Never 27.7
1 2 38 Male Sjælland Asthma 2024-02-02 XBB.1.5 Mild Moderate No ... No NaN No NaN 0 NaN NaN Healthcare Never 21.9
2 3 41 Female Syddanmark Hypertension 2023-05-28 Beta Mild High Yes ... No NaN Yes Janssen 3 2024-05-14 NaN Unemployed Never 22.7
3 4 81 Female Hovedstaden Asthma 2023-08-13 Delta Severe High No ... Yes 2024-08-24 Yes AstraZeneca 1 2024-10-31 NaN Office Worker Never 27.7
4 5 50 Female Syddanmark Cardiovascular 2023-03-10 Delta Mild High No ... No NaN Yes NaN 2 2023-07-05 NaN Student Never 11.9

5 rows × 26 columns

In [20]:
print('Conteo inicial de filas con datos duplicados.')
filas_in = df_limpio.shape[0] #accedemos al indice 0 del metodo shape
df_limpio.drop_duplicates(inplace=True) #con drop eliminamos datos duplicados, inplace es para que lo haga sobre el dataframe copy
filas_de = df_limpio.shape[0]
print(f'Filas iniciales: {filas_in}')
print(f'Filas despues de borrar duplicados: {filas_de}')
print(f'Numero de duplicados eliminados {filas_in - filas_de}\n')
Conteo inicial de filas con datos duplicados.
Filas iniciales: 3000
Filas despues de borrar duplicados: 3000
Numero de duplicados eliminados 0

NOTA:Esta sección detalla la cantidad de filas originales y las que fueron eliminadas. Cabe destacar que no se detectaron duplicados, por lo que ninguna fila fue eliminada por ese motivo.

In [21]:
print('Nombres de las cadenas actuales: ')
print(df_limpio.columns.tolist()) #mostramos el nombre de las columnas en nuestro dataframe, convirtiendo a lista.
Nombres de las cadenas actuales: 
['Patient_ID', 'Age', 'Gender', 'Region', 'Preexisting_Condition', 'Date_of_Infection', 'COVID_Strain', 'Symptoms', 'Severity', 'Hospitalized', 'Hospital_Admission_Date', 'Hospital_Discharge_Date', 'ICU_Admission', 'Ventilator_Support', 'Recovered', 'Date_of_Recovery', 'Reinfection', 'Date_of_Reinfection', 'Vaccination_Status', 'Vaccine_Type', 'Doses_Received', 'Date_of_Last_Dose', 'Long_COVID_Symptoms', 'Occupation', 'Smoking_Status', 'BMI']
In [22]:
print('Conversión de tipos de datos.')
fecha_cols = [
    'Date_of_Infection', 
    'Hospital_Admission_Date',
    'Hospital_Discharge_Date',
    'Date_of_Recovery',
    'Date_of_Reinfection',
    'Date_of_Last_Dose',
] # lista con los valores a convertir a tipo de dato fecha

for col in fecha_cols: 
    if col in df_limpio.columns:
        df_limpio[col] = pd.to_datetime(df_limpio[col], errors='coerce')
        print(f'Columna "{col}" convertida a tipo de dato: {df_limpio[col].dtype}')
    else: 
        print(f'Columna "{col} no fue encontrada')
Conversión de tipos de datos.
Columna "Date_of_Infection" convertida a tipo de dato: datetime64[ns]
Columna "Hospital_Admission_Date" convertida a tipo de dato: datetime64[ns]
Columna "Hospital_Discharge_Date" convertida a tipo de dato: datetime64[ns]
Columna "Date_of_Recovery" convertida a tipo de dato: datetime64[ns]
Columna "Date_of_Reinfection" convertida a tipo de dato: datetime64[ns]
Columna "Date_of_Last_Dose" convertida a tipo de dato: datetime64[ns]
In [23]:
print('Conversión de tipos de datos.')
categoria_cols = [
    'Gender',
    'Region',
    'Preexisting_Condition',
    'COVID_Strain',
    'Symptoms',
    'Severity',
    'Hospitalized',
    'ICU_Admission',
    'Ventilator_Support',
    'Recovered',
    'Reinfection',
    'Vaccination_Status',
    'Vaccine_Type',
    'Doses_Received',  
    'Long_COVID_Symptoms',
    'Occupation',
    'Smoking_Status',
]

for column in categoria_cols:
    if column in df_limpio.columns:
        df_limpio[column] = df_limpio[column].astype(str).str.strip().str.lower()
        df_limpio[column] = df_limpio[column].astype('category')
        print(f"Columna '{column}' convertida a tipo: {df_limpio[column].dtype}")
    else:
        print(f"Columna categórica '{column}' no encontrada.")
Conversión de tipos de datos.
Columna 'Gender' convertida a tipo: category
Columna 'Region' convertida a tipo: category
Columna 'Preexisting_Condition' convertida a tipo: category
Columna 'COVID_Strain' convertida a tipo: category
Columna 'Symptoms' convertida a tipo: category
Columna 'Severity' convertida a tipo: category
Columna 'Hospitalized' convertida a tipo: category
Columna 'ICU_Admission' convertida a tipo: category
Columna 'Ventilator_Support' convertida a tipo: category
Columna 'Recovered' convertida a tipo: category
Columna 'Reinfection' convertida a tipo: category
Columna 'Vaccination_Status' convertida a tipo: category
Columna 'Vaccine_Type' convertida a tipo: category
Columna 'Doses_Received' convertida a tipo: category
Columna 'Long_COVID_Symptoms' convertida a tipo: category
Columna 'Occupation' convertida a tipo: category
Columna 'Smoking_Status' convertida a tipo: category

NOTA: En este caso, los bloques de código anteriores se utilizaron para convertir los tipos de datos en nuestro archivo CSV. Específicamente, las fechas se encontraban inicialmente como tipo de dato object y fueron transformadas a datetime. De manera similar, los datos de tipo object que representaban variables categóricas se cambiaron a category. Estos ajustes son cruciales para facilitar un análisis más preciso y obtener conclusiones mejoradas a partir de los datos.

In [24]:
df_limpio.head()
Out[24]:
Patient_ID Age Gender Region Preexisting_Condition Date_of_Infection COVID_Strain Symptoms Severity Hospitalized ... Reinfection Date_of_Reinfection Vaccination_Status Vaccine_Type Doses_Received Date_of_Last_Dose Long_COVID_Symptoms Occupation Smoking_Status BMI
0 1 69 male hovedstaden obesity 2022-06-21 delta mild moderate yes ... no NaT yes nan 1 2022-09-22 nan healthcare never 27.7
1 2 38 male sjælland asthma 2024-02-02 xbb.1.5 mild moderate no ... no NaT no nan 0 NaT nan healthcare never 21.9
2 3 41 female syddanmark hypertension 2023-05-28 beta mild high yes ... no NaT yes janssen 3 2024-05-14 nan unemployed never 22.7
3 4 81 female hovedstaden asthma 2023-08-13 delta severe high no ... yes 2024-08-24 yes astrazeneca 1 2024-10-31 nan office worker never 27.7
4 5 50 female syddanmark cardiovascular 2023-03-10 delta mild high no ... no NaT yes nan 2 2023-07-05 nan student never 11.9

5 rows × 26 columns

In [25]:
df_limpio.isnull().sum().sum()
Out[25]:
9983

NOTA: Aqui vemos que aun hay 9983 datos nulos en nuestro dataset, los cuales son en su mayoria fecha. Aunque pandas puede trabajar con datos NaT, o Not a Time, los vamos a limpiar de la siguiente forma.

In [26]:
print('Fechas faltantes o NaT en las columnas tipo date')
fecha_nans = [
    'Hospital_Admission_Date',
    'Hospital_Discharge_Date',
    'Date_of_Recovery',
    'Date_of_Reinfection',
    'Date_of_Last_Dose',
]

for col in fecha_nans:

    if col in df_limpio.columns and df_limpio[col].dtype == 'datetime64[ns]':
        df_limpio[f'{col}_fecha_faltante'] = df_limpio[col].isna()
        print(f"Conteo de valores NaT en {col}: {df_limpio[f'{col}_fecha_faltante'].sum()}")
    else:
        print(f"Columna de fecha '{col}' no encontrada o no es de tipo datetime para crear el flag de nulos.")
Fechas faltantes o NaT en las columnas tipo date
Conteo de valores NaT en Hospital_Admission_Date: 2124
Conteo de valores NaT en Hospital_Discharge_Date: 2124
Conteo de valores NaT en Date_of_Recovery: 1492
Conteo de valores NaT en Date_of_Reinfection: 2715
Conteo de valores NaT en Date_of_Last_Dose: 1528

NOTA: Una vez ejecutado el codigo anterior, creara nuevas columnas acorde a si encontro datos tipo fecha faltantes. Estos datos no se imputan o rellenan ya que representan un gran porcentaje de datos faltantes.

4. Análisis Exploratorio de Datos. 📈¶

En esta parte del proyecto, vamos a interactuar directamente con nuestro DataFrame ya limpio para comprender a fondo sus características. Nuestro objetivo principal es identificar patrones ocultos, detectar cualquier anomalía o valor atípico que pueda influir en nuestros análisis, y formular hipótesis iniciales sobre las relaciones entre las variables.

In [27]:
sns.set_style('white')
plt.rcParams['figure.figsize'] = (10,6)
plt.rcParams['figure.dpi'] = 100

4.1. Demografía de la Reinfección: ¿Existen diferencias significativas en la tasa de reinfección entre distintos grupos demográficos (edad, género)? 🌎¶

  • En este primer paso, nos enfocaremos en un análisis crucial: calcular las reinfecciones desagregadas por género. Esto nos permitirá entender si existen diferencias significativas en la tasa de reinfección entre hombres y mujeres, ofreciéndonos una perspectiva inicial valiosa sobre el comportamiento de los datos.
In [28]:
rein_gn = df_limpio.groupby('Gender', observed=False)['Reinfection'].value_counts(normalize=True).unstack()
print('Tasa de reinfección por genero: \n')
print(rein_gn)
Tasa de reinfección por genero: 

Reinfection        no       yes
Gender                         
female       0.899804  0.100196
male         0.910387  0.089613
  • Comenzamos con la visualización de estos datos obtenidos.
In [29]:
plt.figure(figsize=(9, 6))
rein_gn.plot(kind='bar', stacked=False, ax=plt.gca(), color=['#a6cee3', '#1f78b4'])
plt.title('Proporción de Reinfección de COVID-19 por Género.', fontsize=15, fontweight='bold', pad=20)
plt.xlabel('Género', fontsize=12, fontweight='bold', labelpad=10)
plt.ylabel('Proporción', fontsize=12, fontweight='bold', labelpad=20)
plt.xticks(rotation=0, fontsize=10)
plt.yticks(fontsize=10)
plt.legend(title='Reinfección', title_fontsize=12, fontsize=10)
plt.tight_layout()
plt.show()
No description has been provided for this image

NOTA: La gráfica revela que el género no constituye un factor demográfico determinante, puesto que la tasa de reinfección es comparable entre mujeres y hombres.

  • A continuación, graficaremos los datos de edad y casos de reinfección para identificar cualquier patrón.
In [30]:
rein_ed = df_limpio.groupby('Age', observed=False)['Reinfection'].value_counts(normalize=True).unstack()
In [31]:
print('Reinfección por edad: ')
print(rein_ed)
Reinfección por edad: 
Reinfection        no       yes
Age                            
18           0.837209  0.162791
19           0.760870  0.239130
20           0.850000  0.150000
21           0.852941  0.147059
22           0.914286  0.085714
..                ...       ...
85           0.927273  0.072727
86           0.875000  0.125000
87           0.918367  0.081633
88           0.972973  0.027027
89           0.777778  0.222222

[72 rows x 2 columns]
In [32]:
from matplotlib.ticker import PercentFormatter

df_temp = df_limpio.copy()
df_temp['Age'] = pd.to_numeric(df_temp['Age'], errors='coerce')
df_temp.dropna(subset=['Age'], inplace=True)
df_temp['Age'] = df_temp['Age'].astype(int)

bins = [18, 29, 49, 64, 79, df_temp['Age'].max() + 1]
labels = ['18-29', '30-49', '50-64', '65-79', '80+']

df_temp['Age_Group_Temp'] = pd.cut(df_temp['Age'], bins=bins, labels=labels, right=False, include_lowest=True)
df_temp['Age_Group_Temp'] = df_temp['Age_Group_Temp'].astype('category')

rein_ed_grouped = df_temp.groupby('Age_Group_Temp', observed=False)['Reinfection'].value_counts(normalize=True).unstack()
plt.figure(figsize=(10, 8))
ax = rein_ed_grouped.plot(kind='bar', stacked=False, ax=plt.gca(), color=['#a6cee3', '#1f78b4'])

plt.title('Proporción de Reinfección de COVID-19 por Grupo de Edad', fontsize=16, fontweight='bold', pad=20)
plt.xlabel('Grupo de Edad', fontsize=12, fontweight='bold', labelpad=15)
plt.ylabel('Proporción', fontsize=12, fontweight='bold', labelpad=15)
plt.xticks(rotation=45, ha='right', fontsize=10)
plt.yticks(fontsize=10)

ax.yaxis.set_major_formatter(PercentFormatter(xmax=1))
plt.legend(['No Reinfección', 'Reinfección'], title='Estado de Reinfección', title_fontsize=12, fontsize=10, loc='upper left')

for p in ax.patches:
    height = p.get_height()
    if height > 0:
        ax.text(p.get_x() + p.get_width()/2., height + 0.01,
                            '{:.1%}'.format(height), ha="center", fontsize=9, color='black')

plt.grid(axis='y', linestyle='--')
plt.tight_layout(rect=[0, 0, 1, 0.95])
plt.show()
No description has been provided for this image

NOTA: La visualización de la proporción de reinfección de COVID-19 por grupo de edad revela que, de manera general, la tasa de reinfección se mantiene baja en todos los segmentos demográficos. Sin embargo, se observan patrones diferenciados que permiten una interpretación clara de la distribución de la reinfección con respecto a este parámetro demográfico:

  • Los adultos jóvenes (18-29 años) presentan la proporción más alta de reinfección, alcanzando el 13.1%.

  • Posteriormente, los grupos de adultos mayores (65-79 años y 80+ años) muestran las siguientes proporciones más elevadas, con 10.8% y 10.3% respectivamente.

  • En contraste, los grupos de edad media (30-49 años y 50-64 años) exhiben las tasas de reinfección más bajas, con un 7.1% y un 8.3% respectivamente.

Esta distribución sugiere que, si bien la reinfección no es un fenómeno predominante, su incidencia es comparativamente mayor en los segmentos de población más jóvenes y en los extremos de la vida adulta, mientras que disminuye en las edades intermedias.

In [33]:
import plotly.express as px

df_temp = df_limpio.copy()
df_temp['Age'] = pd.to_numeric(df_temp['Age'], errors='coerce')
df_temp.dropna(subset=['Age'], inplace=True)
df_temp['Age'] = df_temp['Age'].astype(int)

bins = [18, 29, 49, 64, 79, df_temp['Age'].max() + 1]
labels = ['18-29', '30-49', '50-64', '65-79', '80+']

df_temp['Age_Group_Temp'] = pd.cut(df_temp['Age'], bins=bins, labels=labels, right=False, include_lowest=True)
df_temp['Age_Group_Temp'] = df_temp['Age_Group_Temp'].astype('category')

combined_gn_ed = pd.crosstab(index=[df_temp['Gender'], df_temp['Age_Group_Temp']], columns=df_temp['Reinfection'])

df_plot = combined_gn_ed.reset_index().melt(
    id_vars=['Gender', 'Age_Group_Temp'],
    var_name='Estado_Reinfeccion',
    value_name='Conteo_Reinfeccion'
)

colors = {
    'no': '#1f78b4',
    'yes': '#D62728'
}

graf = px.bar(
    df_plot,
    x = 'Age_Group_Temp',
    y = 'Conteo_Reinfeccion', 
    color = 'Estado_Reinfeccion',
    facet_col = 'Gender',
    barmode = 'group',
    title = 'Conteo de Reinfecciones por Género y Edad.',
    labels={
        'Age_Group_Temp' : 'Grupo de Edad',
        'Conteo_Reinfeccion' : 'Número de Casos',
        'Estado_Reinfeccion' : 'Estado de Reinfección',
        'Gender' : 'Género'
    },
    hover_data = {'Conteo_Reinfeccion': True},
    color_discrete_map = colors,
)

graf.update_layout(
    title_font_size=20,
    title_font_color='black',
    title_x=0.5,
    xaxis_title_font_size=14,
    yaxis_title_font_size=14,
    legend_title_font_size=14,
    legend_font_size=12,
    hoverlabel=dict(bgcolor="white", font_size=12, font_family="Arial"),
    height=550
)

graf.for_each_annotation(lambda a: a.update(text = a.text.replace("Gender=", "Género: ").replace("female", "Femenino").replace("male", "Masculino")))

graf.show()

NOTA: El gráfico presenta el conteo de casos de reinfección (y no reinfección) desglosado por grupo de edad y género, lo que nos permite explorar patrones más detallados.

  • Se observa que, en la mayoría de los grupos de edad, el número absoluto de casos de reinfección y no reinfección es mayor en hombres que en mujeres.
  • Tanto en hombres como en mujeres, los grupos de edad de 30-49 años y 18-29 años son los que presentan el mayor conteo de reinfecciones. Este patrón sugiere que los adultos jóvenes y de mediana edad son los que más casos absolutos de reinfección tienen, independientemente del género.

¿Existen diferencias significativas en la tasa de reinfección entre distintos grupos demográficos (edad, género)? 🦠¶

Sí, existen diferencias significativas en la tasa de reinfección entre distintos grupos demográficos, especialmente en relación con la edad, mientras que la influencia del género es más sutil y se observa más en el conteo absoluto de casos que en la proporción de reinfección.

Edad.

  • El grupo de adultos jóvenes (18-29 años) muestra la proporción más alta de reinfección, con un 13.1%.
  • Los grupos de adultos mayores (65-79 años y 80+ años) también presentan proporciones elevadas de reinfección, con 10.8% y 10.3% respectivamente.
  • En contraste, los grupos de edad intermedia (30-49 años con 7.1% y 50-64 años con 8.3%) exhiben las proporciones de reinfección más bajas.

Esto sugiere que los extremos del rango de edad adulta (jóvenes y mayores) tienen una mayor proporción de reinfecciones que las edades intermedias.

Género.

  • En términos de conteo absoluto, el gráfico muestra un mayor número de casos de reinfección en hombres comparado con mujeres en la mayoría de los grupos de edad.

Conclusión.📊

La edad es un factor demográfico distintivo que influye en la tasa de reinfección, mostrando patrones claros en diferentes grupos etarios. El género, por otro lado, impacta más en el conteo total de casos que en la proporción de reinfección, lo que sugiere que no es un factor de riesgo proporcional tan marcado como la edad.

4.2 ¿Qué condiciones de salud preexistentes (comorbilidades) están más fuertemente asociadas con un mayor riesgo de reinfección?🌎¶

  • En esta etapa del análisis, nos enfocaremos en investigar la relación entre las condiciones de salud preexistentes (comorbilidades) y la reinfección de COVID-19. Nuestro objetivo principal es determinar si existen comorbilidades que estén fuertemente asociadas con un mayor riesgo de reinfección en los pacientes. Para ello, exploraremos cómo la presencia de estas condiciones influye en la proporción de casos de reinfección.
In [34]:
rein_pc = df_limpio.groupby('Preexisting_Condition', observed=False)['Reinfection'].value_counts(normalize=True).reset_index(name='Proportion')
print('Tasa de reinfección por condición preexistente: \n')
print(rein_pc)
Tasa de reinfección por condición preexistente: 

   Preexisting_Condition Reinfection  Proportion
0                 asthma          no    0.925466
1                 asthma         yes    0.074534
2         cardiovascular          no    0.902439
3         cardiovascular         yes    0.097561
4               diabetes          no    0.908023
5               diabetes         yes    0.091977
6           hypertension          no    0.888438
7           hypertension         yes    0.111562
8                    nan          no    0.891258
9                    nan         yes    0.108742
10               obesity          no    0.913894
11               obesity         yes    0.086106
In [35]:
import plotly.express as px

colors = {
    'no': '#a6cee3',
    'yes': '#1f78b4'
}

grafic = px.bar(
    rein_pc,
    x='Preexisting_Condition',
    y='Proportion',
    color='Reinfection',
    barmode='group',
    title='Proporción de Reinfección de COVID-19 por Condición Preexistente',
    labels={
        'Preexisting_Condition': 'Condición',
        'Proportion': 'Proporción',
        'Reinfection': 'Estado de Reinfección'
    },
    hover_data={'Proportion': ':.1%'},
    text_auto='.1%',
    color_discrete_map=colors
)

grafic.update_layout(
    title_font_size=20,
    title_font_color='black',
    title_x=0.5,
    xaxis_title_font_size=14,
    yaxis_title_font_size=14,
    legend_title_font_size=14,
    legend_font_size=12,
    hoverlabel=dict(bgcolor="white", font_size=12, font_family="Arial"),
    height=550
)

grafic.update_yaxes(tickformat=".0%")

grafic.show()

Qué condiciones de salud preexistentes (comorbilidades) están más fuertemente asociadas con un mayor riesgo de reinfección?📊¶

Aunque la gráfica 'Proporción de Reinfección de COVID-19 por Condición Preexistente' revela que existen condiciones con un porcentaje de reinfección marginalmente más alto que otras, no se observa una correlación fuerte o una disparidad drástica que sugiera que una comorbilidad en particular sea un factor de riesgo significativamente mayor para la reinfección.

Reinfección.🦠

  • La proporción de reinfección entre las comorbilidades mostradas oscila en un rango relativamente estrecho (aproximadamente del 7.5% al 11.2%). Por ejemplo, la hipertensión presenta la proporción más alta con 11.2%, mientras que el asma registra la más baja con 7.5%. Esta diferencia, aunque presente, es moderada y no indica una asociación extremadamente pronunciada.
  • Un punto crucial que se deduce de la gráfica 'Proporción de Reinfección de COVID-19 por Condición Preexistente' es la proporción de reinfección para la categoría 'nan' (10.9%). Dado que 'nan' hace referencia a personas que no presentan ninguna de las condiciones preexistentes listadas, es notable que su porcentaje de reinfección se encuentre por encima de condiciones como el asma (7.5%) y la obesidad (8.6%)

Conclusión.

Estar exento de las comorbilidades específicas analizadas no garantiza un riesgo significativamente menor de reinfección. La proporción de reinfección para este grupo sin condiciones es comparable a la de la hipertensión (11.2%), que es la condición con la tasa más alta. Por lo tanto, el gráfico resalta que las medidas de cuidado y prevención siguen siendo primordiales para evitar una reinfección, independientemente de la presencia o ausencia de estas condiciones de salud preexistentes específicas. Otros factores como la exposición, el comportamiento individual o incluso comorbilidades no incluidas en este análisis podrían estar influyendo en el riesgo de reinfección en la población general.

4.3 ¿Hay una relación entre la gravedad de la infección inicial o la reinfección y los factores de salud del paciente?🧼¶

  • En esta etapa del análisis, nuestro objetivo es investigar si existe una correlación entre la gravedad de la infección inicial por COVID-19 y la probabilidad de una reinfección posterior.

Para lograrlo, se hará uso de las siguientes variables presentes en el dataset, cada una justificando su inclusión por su relevancia en la medición de la severidad de la infección:

  • Severity: Esta variable es fundamental ya que proporciona una clasificación directa de la severidad de la infección inicial (ej., asintomática, leve, moderada, grave). Su análisis nos permitirá identificar rápidamente si existe un patrón claro de reinfección a través de los distintos grados de severidad.
  • Hospitalized: La hospitalización es un indicador clave de una infección más grave que requirió atención médica especializada y monitoreo. Evaluar su asociación con la reinfección nos ayudará a entender si el hecho de haber sido internado por la infección inicial impacta la probabilidad de una subsiguiente.
In [36]:
rein_sl = df_limpio.groupby('Severity', observed=False)['Reinfection'].value_counts(normalize=True).reset_index(name='Proportion')
print('Tasa de reinfección por severidad: \n')
print(rein_sl)
Tasa de reinfección por severidad: 

   Severity Reinfection  Proportion
0  critical          no    0.902954
1  critical         yes    0.097046
2      high          no    0.891645
3      high         yes    0.108355
4       low          no    0.909836
5       low         yes    0.090164
6  moderate          no    0.915297
7  moderate         yes    0.084703
In [37]:
rein_hs = df_limpio.groupby('Hospitalized', observed=False)['Reinfection'].value_counts(normalize=True).reset_index(name='Proportion')
print('Tasa de reinfección por hospitalización: \n')
print(rein_hs)
Tasa de reinfección por hospitalización: 

  Hospitalized Reinfection  Proportion
0           no          no    0.904426
1           no         yes    0.095574
2          yes          no    0.906393
3          yes         yes    0.093607
In [38]:
import plotly.express as px

colors = {
    'no': '#a6cee3',
    'yes': '#1f78b4'
}

grafic1 = px.bar(
    rein_sl,
    x='Severity',
    y='Proportion',
    color='Reinfection',
    barmode='group',
    title='Proporción de Reinfección de COVID-19 por Severidad',
    labels={
        'Severity': 'Severidad',
        'Proportion': 'Proporción',
        'Reinfection': 'Estado de Reinfección'
    },
    hover_data={'Proportion': ':.1%'},
    text_auto='.1%',
    color_discrete_map=colors
)

grafic1.update_layout(
    title_font_size=20,
    title_font_color='black',
    title_x=0.5,
    xaxis_title_font_size=14,
    yaxis_title_font_size=14,
    legend_title_font_size=14,
    legend_font_size=12,
    hoverlabel=dict(bgcolor="white", font_size=12, font_family="Arial"),
    height=550
)

grafic1.update_yaxes(tickformat=".0%")

grafic1.show()

NOTA: La gráfica revela que los pacientes con una severidad inicial 'high' (alta) y 'critical' (crítica) presentan las proporciones más elevadas de reinfección, con 10.8% y 9.7% respectivamente. Estos porcentajes son ligeramente superiores a los de los casos 'low' (bajos) con 9.0% y 'moderate' (moderados) con 8.5%.

In [39]:
import plotly.express as px

colors = {
    'no': '#a6cee3',
    'yes': '#1f78b4'
}

grafic2 = px.bar(
    rein_hs,
    x='Hospitalized',
    y='Proportion',
    color='Reinfection',
    barmode='group',
    title='Proporción de Reinfección de COVID-19 por Condición Preexistente',
    labels={
        'Hospitalized': 'Hospitalización',
        'Proportion': 'Proporción',
        'Reinfection': 'Estado de Reinfección'
    },
    hover_data={'Proportion': ':.1%'},
    text_auto='.1%',
    color_discrete_map=colors
)

grafic2.update_layout(
    title_font_size=20,
    title_font_color='black',
    title_x=0.5,
    xaxis_title_font_size=14,
    yaxis_title_font_size=14,
    legend_title_font_size=14,
    legend_font_size=12,
    hoverlabel=dict(bgcolor="white", font_size=12, font_family="Arial"),
    height=550
)

grafic2.update_yaxes(tickformat=".0%")

grafic2.show()

NOTA: No se observa una diferencia significativa en la proporción de reinfección entre los pacientes que fueron hospitalizados y los que no.

4.3 ¿Hay una relación entre la gravedad de la infección inicial o la reinfección y los factores de salud del paciente?🦠¶

Severidad.

Existe una asociación entre la gravedad de la infección inicial y la proporción de reinfección. Los pacientes que experimentaron una infección inicial más severa ('critical' y 'high') parecen tener una proporción de reinfección ligeramente mayor en comparación con aquellos con infecciones leves a moderadas. Esto podría indicar que la severidad de la infección inicial no necesariamente confiere una inmunidad más robusta que proteja contra la reinfección, o que hay otros factores asociados a la severidad que aumentan la susceptibilidad.

Hospitalización.

En esta variable no se pudo observar alguna relación entre porcentajes, ya que ambos casos son similares.

Conclusión Total.📈¶

Las visualizaciones demográficas y de salud preexistente revelan que la edad es un factor demográfico clave que influye en la proporción de reinfección, mostrando patrones de mayor riesgo en adultos jóvenes y mayores. Si bien los hombres presentan un mayor conteo absoluto de reinfecciones, la proporción de reinfección por género es más similar. En cuanto a las condiciones preexistentes, aunque hay variaciones, no se identifica una comorbilidad con un riesgo drásticamente elevado de reinfección, y la alta proporción de reinfección en el grupo sin condiciones específicas subraya que la ausencia de estas no elimina un riesgo considerable. Finalmente, la gravedad de la infección inicial también muestra una asociación, con casos más severos ('critical' y 'high') presentando una proporción de reinfección ligeramente superior. En conjunto, esto sugiere que la reinfección es un fenómeno multifactorial donde la edad, la severidad de la infección inicial y, en menor medida, ciertas comorbilidades pueden jugar un papel, pero la prevención sigue siendo universalmente importante.⚠️

Herramientas utilizadas en este proyecto.⚙️¶

  • Jupyter Notebook.🌎
  • Python, Pandas, Plotly Express, Matplotlib.🐍