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.
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.
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
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 acategory
oboolean
, 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.
df_limpio = df.copy() #creamos una copia del dataframe original
df_limpio.head() #mostramos las primeras 5 filas para verificar que se cargo el dataframe a limpiar
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
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.
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']
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]
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.
df_limpio.head()
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
df_limpio.isnull().sum().sum()
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.
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.
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.
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.
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()
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.
rein_ed = df_limpio.groupby('Age', observed=False)['Reinfection'].value_counts(normalize=True).unstack()
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]
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()
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.
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.
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
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.
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
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
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%.
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.🐍