Ejemplo de cuaderno para el proyecto final#

Para la entrega final podrás entregar un cuaderno como el siguiente. Este cuaderno te puede servir de guía, e incluso puedes intentar replicarlo para obtener resultados similares :)

⚠️ Para ver las visualizaciones es necesario que hagas clic en el botón “Open in Colab” que aparece en la parte superior de la página.

Open In Colab

Importar datos#

Con “importar datos” nos referimos a la manera en la que preparamos la fuente de datos para ser leída por nuestro programa.

Existen múltiples maneras de importar la información. Por ejemplo, podemos sencillamente utilizar el mismo método que usamos con nuestro archivo ejemplo-1.txt.

Descarga el archivo que quieras utilizar en el directorio de Drive en el que vayas a almacenar tus datos.

Como ejemplo, voy a utilizar los casos nacionales de COVID-19 registrados diariamente durante el primer semestre de 2022: https://datos.cdmx.gob.mx/dataset/casos-asociados-a-covid-19/resource/e5f65f40-5904-492a-ae33-1ea98fb73d78?inner_span=True

Descargo el archivo CSV en un directorio de mi computadora. Posteriormente lo subo a mi directorio de datos de Google Drive:

Volvemos a nuestro cuaderno de Google Colab. Me aseguro de haber activado Google Drive en mi Google Colab y busco el directorio en el cual está mi archivo. En mi caso: '/content/drive/MyDrive/Colab Notebooks/curso_datos/casos_nacionales_covid-19_2022_semestre1.csv'

Con esos pasos, podemos hacer la importación:

datos = '/content/drive/MyDrive/Colab Notebooks/curso_datos/casos_nacionales_covid-19_2022_semestre1.csv'

with open(datos, 'r') as f:
  data = f.readlines(10) # agrego este argumento porque el archivo es muy extenso.

data
['"","fecha_actualizacion","id_registro","origen","sector","entidad_um","sexo","entidad_nac","entidad_res","municipio_res","tipo_paciente","fecha_ingreso","fecha_sintomas","fecha_def","intubado","neumonia","edad","nacionalidad","embarazo","habla_lengua_indig","indigena","diabetes","epoc","asma","inmusupr","hipertension","otra_com","cardiovascular","obesidad","renal_cronica","tabaquismo","otro_caso","toma_muestra_lab","resultado_lab","toma_muestra_antigeno","resultado_antigeno","clasificacion_final","migrante","pais_nacionalidad","pais_origen","uci"\n']

De esta manera hemos logrado incluir el archivo en nuestro cuaderno, pero será muy complejo manipularlo. Por esta razón, es preferible utilizar una librería que nos ayude a procesar estos datos. En nuestro caso, usaremos ‘Pandas’

Para hacer que nuestro programa funcione, solamente debemos importar la librería:

import pandas as pd

Y posteriormente podremos abrir nuestro archivo desde Python:

import pandas as pd

covid_nacional = pd.read_csv(datos)
covid_nacional.head()
/usr/local/lib/python3.7/dist-packages/IPython/core/interactiveshell.py:3326: DtypeWarning: Columns (13) have mixed types.Specify dtype option on import or set low_memory=False.
  exec(code_obj, self.user_global_ns, self.user_ns)
Unnamed: 0 fecha_actualizacion id_registro origen sector entidad_um sexo entidad_nac entidad_res municipio_res ... otro_caso toma_muestra_lab resultado_lab toma_muestra_antigeno resultado_antigeno clasificacion_final migrante pais_nacionalidad pais_origen uci
0 1 2022-06-26 0793b8 FUERA DE USMER SSA CIUDAD DE MÉXICO HOMBRE CIUDAD DE MÉXICO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 NO ESPECIFICADO MÉXICO NO APLICA NO APLICA
1 2 2022-06-26 0fef08 USMER SSA CIUDAD DE MÉXICO HOMBRE CIUDAD DE MÉXICO NaN NaN ... NO SI POSITIVO A SARS-COV-2 NO NO APLICA (CASO SIN MUESTRA) CASO DE SARS-COV-2 CONFIRMADO NO ESPECIFICADO MÉXICO NO APLICA NO APLICA
2 3 2022-06-26 11e31a FUERA DE USMER SSA CIUDAD DE MÉXICO HOMBRE CIUDAD DE MÉXICO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 NO ESPECIFICADO MÉXICO NO APLICA NO APLICA
3 4 2022-06-26 0741e4 FUERA DE USMER ISSSTE CIUDAD DE MÉXICO HOMBRE CIUDAD DE MÉXICO NaN NaN ... NO SI RESULTADO NO ADECUADO NO NO APLICA (CASO SIN MUESTRA) NO REALIZADO POR LABORATORIO NO ESPECIFICADO MÉXICO NO APLICA NO
4 5 2022-06-26 13c92b FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER CIUDAD DE MÉXICO NaN NaN ... SI NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 NO ESPECIFICADO MÉXICO NO APLICA NO APLICA

5 rows × 41 columns

De esta manera, nuestro archivo estará listo para ser procesado :)

Análisis de estructuras de datos y preparación#

Describe la fuente de datos#

Una descripción simple de la forma de la fuente de datos es la siguiente:

# número de filas
filas = covid_nacional.shape[0]
filas
1323501

Esta es una fuente de datos con suficientes campos como para justificar una lectura distante de la información. Difícilmente una persona podría comprender la información que hay en ella solamente “leyendo” los datos de esas tablas.

# número de columnas
columnas = covid_nacional.shape[1]
columnas
41

Además, vemos que es un conjunto de datos con una cantidad significativa de categorías. Esto permite que con una sola fuente de información se puedan realizar operaciones de comparación entre columnas para analizar la información.

# nombre de las columnas
covid_nacional.columns
Index(['Unnamed: 0', 'fecha_actualizacion', 'id_registro', 'origen', 'sector',
       'entidad_um', 'sexo', 'entidad_nac', 'entidad_res', 'municipio_res',
       'tipo_paciente', 'fecha_ingreso', 'fecha_sintomas', 'fecha_def',
       'intubado', 'neumonia', 'edad', 'nacionalidad', 'embarazo',
       'habla_lengua_indig', 'indigena', 'diabetes', 'epoc', 'asma',
       'inmusupr', 'hipertension', 'otra_com', 'cardiovascular', 'obesidad',
       'renal_cronica', 'tabaquismo', 'otro_caso', 'toma_muestra_lab',
       'resultado_lab', 'toma_muestra_antigeno', 'resultado_antigeno',
       'clasificacion_final', 'migrante', 'pais_nacionalidad', 'pais_origen',
       'uci'],
      dtype='object')

El nombre de las columnas nos ayuda a identificar las categorías y posibles datos que contienen nuestra fuente de datos.

No todas las fuentes de datos nombran sus columnas de manera significativa. En el caso de nuestro ejemplo, es bastante sencillo identificar qué tipo de información contiene cada categoría o columna, incluso qué tipo de dato sería deseable que tuviese cada una.

Tipos de datos con dtypes()#

covid_nacional.dtypes
Unnamed: 0                int64
fecha_actualizacion      object
id_registro              object
origen                   object
sector                   object
entidad_um               object
sexo                     object
entidad_nac              object
entidad_res              object
municipio_res            object
tipo_paciente            object
fecha_ingreso            object
fecha_sintomas           object
fecha_def                object
intubado                 object
neumonia                 object
edad                      int64
nacionalidad             object
embarazo                 object
habla_lengua_indig       object
indigena                 object
diabetes                 object
epoc                     object
asma                     object
inmusupr                 object
hipertension             object
otra_com                 object
cardiovascular           object
obesidad                 object
renal_cronica            object
tabaquismo               object
otro_caso                object
toma_muestra_lab         object
resultado_lab            object
toma_muestra_antigeno    object
resultado_antigeno       object
clasificacion_final      object
migrante                 object
pais_nacionalidad        object
pais_origen              object
uci                      object
dtype: object

La mayoría de los datos se encuentran representados como tipo object, es decir, que son de tipo texto, numérico-textual o mixto.

Aunque hay columnas que podrían tener un tipo de dato datetime, están representadas en tipo object. Esas columnas deberán ser transformadas para poder hacer operaciones y visualizaciones.

Descripción de los datos con describe()#

covid_nacional.describe()
Unnamed: 0 edad
count 1.323501e+06 1.323501e+06
mean 6.617510e+05 3.774596e+01
std 3.820620e+05 1.728453e+01
min 1.000000e+00 0.000000e+00
25% 3.308760e+05 2.500000e+01
50% 6.617510e+05 3.600000e+01
75% 9.926260e+05 5.000000e+01
max 1.323501e+06 1.220000e+02

De modo predeterminado, pandas describe los datos numéricos int64. De estos solamente nos sería útil edad, pues Unnamed: 0 es un índice (valor nominal).

covid_nacional.describe(include='all')
Unnamed: 0 fecha_actualizacion id_registro origen sector entidad_um sexo entidad_nac entidad_res municipio_res ... otro_caso toma_muestra_lab resultado_lab toma_muestra_antigeno resultado_antigeno clasificacion_final migrante pais_nacionalidad pais_origen uci
count 1.323501e+06 1323501 1323501 1323501 1323501 1323501 1323501 1323501 149707 149707 ... 1323501 1323501 1323501 1323501 1323501 1323501 1323501 1323501 1320040 1323501
unique NaN 1 1323501 2 12 32 2 33 23 1190 ... 3 2 5 2 3 7 3 122 1 4
top NaN 2022-06-26 0793b8 FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER CIUDAD DE MÉXICO MÉXICO NEZAHUALCÓYOTL ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 NO ESPECIFICADO MÉXICO NO APLICA NO APLICA
freq NaN 1323501 1 1170267 793606 1314661 733991 1052272 133374 26282 ... 848434 1152385 1152385 1204565 771647 792364 1305180 1304673 1320040 1297093
mean 6.617510e+05 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
std 3.820620e+05 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
min 1.000000e+00 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
25% 3.308760e+05 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
50% 6.617510e+05 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
75% 9.926260e+05 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
max 1.323501e+06 NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

11 rows × 41 columns

El parámetro include='all' obliga a realizar la operación en todas las columnas.

Esto permite identificar algunas columnas con ciertas frecuencias que podrían ser sujeto de análisis. Por ejemplo, correlaciones entre enfermedades crónicas y resultados (positivos o negativos), o frecuencias de casos de migrantes, mujeres o indígenas relacionadas con un área geográfica.

Debido a que esta fuente de datos no cuenta con información georeferenciada (contamos con los nombres de los municipios, pero no la información de latitud y longitud) será necesario utilizar una fuente de datos que permita agregar esa información.

Procesamiento de datos#

Manipulación de datos#

Aplicación del método .iloc para localizar filas y columnas por índice:

covid_nacional.iloc[2:200, 1:3]
fecha_actualizacion id_registro
2 2022-06-26 11e31a
3 2022-06-26 0741e4
4 2022-06-26 13c92b
5 2022-06-26 04f190
6 2022-06-26 0a1655
... ... ...
195 2022-06-26 485cdb
196 2022-06-26 984dc6
197 2022-06-26 4b5708
198 2022-06-26 bb8b5b
199 2022-06-26 cc68e2

198 rows × 2 columns

Aplicación del método .loc para hallar celdas por coincidencias:

seleccion = covid_nacional.loc[(covid_nacional['sexo'] == 'MUJER') & (covid_nacional['migrante'] == 'SI')]
seleccion
Unnamed: 0 fecha_actualizacion id_registro origen sector entidad_um sexo entidad_nac entidad_res municipio_res ... otro_caso toma_muestra_lab resultado_lab toma_muestra_antigeno resultado_antigeno clasificacion_final migrante pais_nacionalidad pais_origen uci
252 253 2022-06-26 b94888 FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... SI NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI VENEZUELA NaN NO APLICA
971 972 2022-06-26 d22ed2 USMER SSA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... SI NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI ESTADOS UNIDOS DE AMÉRICA NaN NO APLICA
979 980 2022-06-26 6a5061 USMER SSA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... SI NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI ESTADOS UNIDOS DE AMÉRICA NaN NO APLICA
5877 5878 2022-06-26 ac1990 FUERA DE USMER PRIVADA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI ESTADOS UNIDOS DE AMÉRICA NaN NO APLICA
6666 6667 2022-06-26 8d5273 FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI CUBA NaN NO APLICA
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
1298223 1298224 2022-06-26 g16c3a9 FUERA DE USMER PRIVADA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI ITALIA NaN NO APLICA
1305240 1305241 2022-06-26 g154063 FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI EL SALVADOR NaN NO APLICA
1305279 1305280 2022-06-26 g1683fe FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI GUATEMALA NaN NO APLICA
1316685 1316686 2022-06-26 g0ebf9f FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI REPÚBLICA DE HONDURAS NaN NO APLICA
1319864 1319865 2022-06-26 g093480 FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER NO ESPECIFICADO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 SI CHILE NaN NO APLICA

1611 rows × 41 columns

Renombramos las columnas para poder realizar correctamente la unión entre dos dataframes:

covid_nacional.rename(columns={
    "entidad_nac": "entidad_nacimiento",
    "entidad_res": "entidad_residencia",
    "municipio_res": "municipio_residencia"
}, inplace=True)
covid_nacional[7:10]
Unnamed: 0 fecha_actualizacion id_registro origen sector entidad_um sexo entidad_nacimiento entidad_residencia municipio_residencia ... otro_caso toma_muestra_lab resultado_lab toma_muestra_antigeno resultado_antigeno clasificacion_final migrante pais_nacionalidad pais_origen uci
7 8 2022-06-26 0ba73d FUERA DE USMER ISSSTE CIUDAD DE MÉXICO MUJER QUERÉTARO MÉXICO NAUCALPAN DE JUÁREZ ... NO NO NO APLICA (CASO SIN MUESTRA) NO NO APLICA (CASO SIN MUESTRA) CASO SOSPECHOSO NO ESPECIFICADO MÉXICO NO APLICA NO APLICA
8 9 2022-06-26 0681f2 FUERA DE USMER SSA CIUDAD DE MÉXICO HOMBRE CIUDAD DE MÉXICO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI NEGATIVO A SARS-COV-2 NEGATIVO A SARS-COV-2 NO ESPECIFICADO MÉXICO NO APLICA NO APLICA
9 10 2022-06-26 0a98b4 FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER MICHOACÁN DE OCAMPO NaN NaN ... NO NO NO APLICA (CASO SIN MUESTRA) SI POSITIVO A SARS-COV-2 CASO DE SARS-COV-2 CONFIRMADO NO ESPECIFICADO MÉXICO NO APLICA NO APLICA

3 rows × 41 columns

Merge#

Nuevo conjunto de datos para realizar la combinación:

ruta_areas_inegi = '/content/drive/MyDrive/Colab Notebooks/curso_datos/AGEEML_2022842026272.csv'
areas_inegi = pd.read_csv(ruta_areas_inegi)
areas_inegi.head()
Mapa Cve_Ent Nom_Ent Nom_Abr Cve_Mun Nom_Mun Cve_Loc Nom_Loc Ámbito Latitud Longitud Lat_Decimal Lon_Decimal Altitud Cve_Carta Pob_Total Pob_Masculina Pob_Femenina Total De Viviendas Habitadas
0 10010001 1 Aguascalientes Ags. 1 Aguascalientes 1 Aguascalientes U 21°52´47.362N" 102°17´45.768W" 21.879823 -102.296047 1878 F13D19 863893 419168 444725 246259
1 10010094 1 Aguascalientes Ags. 1 Aguascalientes 94 Granja Adelita R 21°52´18.749N" 102°22´24.710W" 21.871875 -102.373531 1901 F13D18 5 * * 2
2 10010096 1 Aguascalientes Ags. 1 Aguascalientes 96 Agua Azul R 21°53´01.522N" 102°21´25.639W" 21.883756 -102.357122 1861 F13D18 41 24 17 12
3 10010100 1 Aguascalientes Ags. 1 Aguascalientes 100 Rancho Alegre R 21°51´16.556N" 102°22´21.884W" 21.854599 -102.372746 1879 F13D18 0 0 0 0
4 10010102 1 Aguascalientes Ags. 1 Aguascalientes 102 Los Arbolitos [Rancho] R 21°46´48.650N" 102°21´26.261W" 21.780181 -102.357295 1861 F13D18 8 * * 2

Pasos previos para el inner merge#

Para nuestros conjuntos de datos requiere un inner merge para geolocalizar los datos. Pero para ello requeriremos realizar algunas tareas previas:

1. Renombrar columna para unión en el segundo dataframe#

areas_inegi.rename(
    columns={'Nom_Mun':'municipio_residencia'}, # recordemos que cambiamos el nombre de la columna en el ejercicio anterior
    inplace=True)
areas_inegi.head()
Mapa Cve_Ent Nom_Ent Nom_Abr Cve_Mun municipio_residencia Cve_Loc Nom_Loc Ámbito Latitud Longitud Lat_Decimal Lon_Decimal Altitud Cve_Carta Pob_Total Pob_Masculina Pob_Femenina Total De Viviendas Habitadas
0 10010001 1 Aguascalientes Ags. 1 Aguascalientes 1 Aguascalientes U 21°52´47.362N" 102°17´45.768W" 21.879823 -102.296047 1878 F13D19 863893 419168 444725 246259
1 10010094 1 Aguascalientes Ags. 1 Aguascalientes 94 Granja Adelita R 21°52´18.749N" 102°22´24.710W" 21.871875 -102.373531 1901 F13D18 5 * * 2
2 10010096 1 Aguascalientes Ags. 1 Aguascalientes 96 Agua Azul R 21°53´01.522N" 102°21´25.639W" 21.883756 -102.357122 1861 F13D18 41 24 17 12
3 10010100 1 Aguascalientes Ags. 1 Aguascalientes 100 Rancho Alegre R 21°51´16.556N" 102°22´21.884W" 21.854599 -102.372746 1879 F13D18 0 0 0 0
4 10010102 1 Aguascalientes Ags. 1 Aguascalientes 102 Los Arbolitos [Rancho] R 21°46´48.650N" 102°21´26.261W" 21.780181 -102.357295 1861 F13D18 8 * * 2

2. Normalizar la columna común#

covid_nacional['municipio_residencia'] = covid_nacional['municipio_residencia'].str.lower()
areas_inegi['municipio_residencia'] = areas_inegi['municipio_residencia'].str.lower()

3. Segmentación de la información#

areas_inegi_tm = areas_inegi.loc[areas_inegi['Cve_Loc'] == 1]

Realización del inner merge#

conjunto_datos = pd.merge(covid_nacional, areas_inegi_tm, how='inner', on='municipio_residencia')
print(conjunto_datos.shape)
conjunto_datos.head()
(158085, 59)
Unnamed: 0 fecha_actualizacion id_registro origen sector entidad_um sexo entidad_nacimiento entidad_residencia municipio_residencia ... Latitud Longitud Lat_Decimal Lon_Decimal Altitud Cve_Carta Pob_Total Pob_Masculina Pob_Femenina Total De Viviendas Habitadas
0 8 2022-06-26 0ba73d FUERA DE USMER ISSSTE CIUDAD DE MÉXICO MUJER QUERÉTARO MÉXICO naucalpan de juárez ... 19°28´43.690N" 099°13´59.585W" 19.478803 -99.233218 2280 E14A39 776220 373698 402522 225509
1 143 2022-06-26 588e9b FUERA DE USMER SSA CIUDAD DE MÉXICO MUJER CIUDAD DE MÉXICO MÉXICO naucalpan de juárez ... 19°28´43.690N" 099°13´59.585W" 19.478803 -99.233218 2280 E14A39 776220 373698 402522 225509
2 154 2022-06-26 51860a USMER SSA CIUDAD DE MÉXICO HOMBRE CIUDAD DE MÉXICO MÉXICO naucalpan de juárez ... 19°28´43.690N" 099°13´59.585W" 19.478803 -99.233218 2280 E14A39 776220 373698 402522 225509
3 912 2022-06-26 de16a0 USMER SSA CIUDAD DE MÉXICO MUJER CIUDAD DE MÉXICO MÉXICO naucalpan de juárez ... 19°28´43.690N" 099°13´59.585W" 19.478803 -99.233218 2280 E14A39 776220 373698 402522 225509
4 1032 2022-06-26 5f39e3 USMER SSA CIUDAD DE MÉXICO HOMBRE GUANAJUATO MÉXICO naucalpan de juárez ... 19°28´43.690N" 099°13´59.585W" 19.478803 -99.233218 2280 E14A39 776220 373698 402522 225509

5 rows × 59 columns

Limpieza de datos#

Segmentación por columnas útiles#

muestra_covid = conjunto_datos[['sexo', 'edad', 'entidad_nacimiento', 'municipio_residencia', 'indigena', 'nacionalidad', 'migrante', 'pais_nacionalidad', 'fecha_ingreso', 'fecha_sintomas', 'fecha_def', 'municipio_residencia', 'Lat_Decimal', 'Lon_Decimal']]
muestra_covid.head()
sexo edad entidad_nacimiento municipio_residencia indigena nacionalidad migrante pais_nacionalidad fecha_ingreso fecha_sintomas fecha_def municipio_residencia Lat_Decimal Lon_Decimal
0 MUJER 75 QUERÉTARO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-02-21 2022-02-16 NaN naucalpan de juárez 19.478803 -99.233218
1 MUJER 32 CIUDAD DE MÉXICO naucalpan de juárez NO ESPECIFICADO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-07 2022-01-02 NaN naucalpan de juárez 19.478803 -99.233218
2 HOMBRE 30 CIUDAD DE MÉXICO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-02-04 2022-02-03 NaN naucalpan de juárez 19.478803 -99.233218
3 MUJER 51 CIUDAD DE MÉXICO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-01 2021-12-28 NaN naucalpan de juárez 19.478803 -99.233218
4 HOMBRE 83 GUANAJUATO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-01 2021-12-30 NaN naucalpan de juárez 19.478803 -99.233218

Lidiar con datos nulos#

muestra_covid.fillna({'municipio_residencia': 'NO APLICA', 'pais_nacionalidad': 'NO APLICA'}, inplace=True)
muestra_covid
/usr/local/lib/python3.7/dist-packages/pandas/core/frame.py:5182: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  downcast=downcast,
/usr/local/lib/python3.7/dist-packages/pandas/core/generic.py:6392: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  return self._update_inplace(result)
sexo edad entidad_nacimiento municipio_residencia indigena nacionalidad migrante pais_nacionalidad fecha_ingreso fecha_sintomas fecha_def municipio_residencia Lat_Decimal Lon_Decimal
0 MUJER 75 QUERÉTARO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-02-21 2022-02-16 NaN naucalpan de juárez 19.478803 -99.233218
1 MUJER 32 CIUDAD DE MÉXICO naucalpan de juárez NO ESPECIFICADO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-07 2022-01-02 NaN naucalpan de juárez 19.478803 -99.233218
2 HOMBRE 30 CIUDAD DE MÉXICO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-02-04 2022-02-03 NaN naucalpan de juárez 19.478803 -99.233218
3 MUJER 51 CIUDAD DE MÉXICO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-01 2021-12-28 NaN naucalpan de juárez 19.478803 -99.233218
4 HOMBRE 83 GUANAJUATO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-01 2021-12-30 NaN naucalpan de juárez 19.478803 -99.233218
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
158080 HOMBRE 12 VERACRUZ DE IGNACIO DE LA LLAVE amatlán de los reyes NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-23 2022-06-23 NaN amatlán de los reyes 18.847578 -96.915484
158081 MUJER 46 CIUDAD DE MÉXICO amatlán de los reyes NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-22 2022-06-19 NaN amatlán de los reyes 18.847578 -96.915484
158082 MUJER 59 CIUDAD DE MÉXICO general simón bolívar NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-23 2022-06-22 NaN general simón bolívar 24.689074 -103.225975
158083 MUJER 27 MÉXICO temozón NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-24 2022-06-22 NaN temozón 20.803680 -88.201158
158084 MUJER 32 MÉXICO izamal NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-24 2022-06-20 NaN izamal 20.932998 -89.019715

158085 rows × 14 columns

Transformar datos#

columnas = ['fecha_ingreso', 'fecha_sintomas', 'fecha_def']
for columna in columnas:
    muestra_covid[columna] = pd.to_datetime(muestra_covid.loc[:, columna])

muestra_covid.dtypes
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:3: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  This is separate from the ipykernel package so we can avoid doing imports until
sexo                            object
edad                             int64
entidad_nacimiento              object
municipio_residencia            object
indigena                        object
nacionalidad                    object
migrante                        object
pais_nacionalidad               object
fecha_ingreso           datetime64[ns]
fecha_sintomas          datetime64[ns]
fecha_def               datetime64[ns]
municipio_residencia            object
Lat_Decimal                    float64
Lon_Decimal                    float64
dtype: object

Georeferenciar los datos de pais_nacionalidad#

# obtener librería pycountry
!pip install pycountry
import pycountry
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Requirement already satisfied: pycountry in /usr/local/lib/python3.7/dist-packages (22.3.5)
Requirement already satisfied: setuptools in /usr/local/lib/python3.7/dist-packages (from pycountry) (57.4.0)
# Función para convertir los datos a iso en español

import gettext

# Esta corrección es necesaria para incluir una serie de países que de otra manera quedarían excluidos
# Se excluyeron las siguientes claves por ser ambiguas o no localizables: 'OTRO', 'SE DESCONOCE', 'REPÚBLICA CHECA Y REPÚBLICA ESLOVACA', 'PAÍSES DE LA EX-U.R.S.S., EXCEPTO UCRANIA Y BIELORUSIA', 'AZERBAIYÁN - ISLAS AZORES'

correccion_paises = {
        'nombre_original': ['ESTADOS UNIDOS DE AMÉRICA', 'VENEZUELA', 'TAIWÁN', 'HOLANDA', 'REPÚBLICA DE HONDURAS', 'BOLIVIA',
                            'REPÚBLICA DE COREA', 'GRAN BRETAÑA (REINO UNIDO)', 'RUSIA',
                            'REPÚBLICA DE COSTA RICA', 'REPÚBLICA DE PANAMÁ',
                            'REPÚBLICA ORIENTAL DEL URUGUAY',
                            'RUMANIA', 'IRÁN', 'ESTADO LIBRE ASOCIADO DE PUERTO RICO',
                            'ESTADO DE KUWAIT', 'ANTIGUA Y BERMUDA',
                            'CAMPIONE DITALIA',
                            'EMIRATOS ARABES UNIDOS',
                            'ZONA ESPECIAL CANARIA', 'COMMONWEALTH DE DOMINICA',
                            'THAILANDIA', 'ESTADO DE BAHREIN', 'MALÍ',
                            'ISLAS MENORES ALEJADAS DE LOS ESTADOS UNIDOS', 'GUYANA FRANCESA',
                            'IRAQ'],
        'nombre_corregido': ['ESTADOS UNIDOS', 'VENEZUELA, REPÚBLICA BOLIVARIANA DE', 'TAIWÁN, PROVINCIA DE CHINA', 'PAÍSES BAJOS', 'HONDURAS', 'BOLIVIA, ESTADO PLURINACIONAL de',
                             'COREA, REPÚBLICA DE', 'Reino Unido', 'FEDERACIÓN RUSA',
                             'COSTA RICA', 'PANAMÁ', 'URUGUAY', 'rumanía', 'irán, república islámica de', 'Puerto rico', 'KUWAIT', 'ANTIGUA Y BARBUDA', 'ITALIA', 'EMIRATOS ÁRABES UNIDOS', 'ESPAÑA', 'DOMINICA', 'TAILANDIA', 'BAHREIN', 'MALI', 'ESTADOS UNIDOS', 'GUYANA', 'IRAK']
    }


none_countries = {'nombre': ['ZONA NEUTRAL', 'COSTA DE MARFIL', 'REPÚBLICA DEMOCRÁTICA DE COREA', 'ARGELIA', 'NUEVA ZELANDIA', 'ARABIA SAUDITA', 'REPÚBLICA CENTRO AFRICANA', 'SUDÁFRICA'],
                  'alpha2': ['NT', 'CI', 'KP', 'DZ', 'NZ', 'SA', 'CF', 'ZA'],
                  'alpha3': ['NTZ', 'CIV', 'PRK', 'DZA', 'NZL', 'SAU', 'CAF', 'ZAF']}


def map_country_code(country_name, language, iso):
    '''
    country_name: str. El nombre del país en español.
    language: str. El idioma en el que se desea obtener el código (p. ej: 'es').
    iso: str. Opciones posibles: 'alpha_2' o 'alpha_3'.
    '''
    try:
        if country_name is None:
            return None
        # esta condición sintetiza el caso de México (reduce de 5 minutos a 6 segundos el tiempo de ejecución)
        elif country_name == 'MÉXICO':
            if iso == 'alpha_2':
                return 'MX'
            elif iso == 'alpha_3':
                return 'MEX'

        spanish = gettext.translation(
            'iso3166', pycountry.LOCALES_DIR, languages=[language])
        spanish.install()
        _ = spanish.gettext

        # check if country_name is in correccion_paises['nombre_original'] and correct it with correccion_paises['nombre_corregido']
        if country_name in correccion_paises['nombre_original']:
            country_name = correccion_paises['nombre_corregido'][correccion_paises['nombre_original'].index(country_name)] 

        if country_name in none_countries['nombre']:
            if iso == 'alpha_2':
                return none_countries['alpha2'][none_countries['nombre'].index(country_name)]
            elif iso == 'alpha_3':
                return none_countries['alpha3'][none_countries['nombre'].index(country_name)]
        else:
            for english_country in pycountry.countries:
                country_name = country_name.lower()
                spanish_country = _(english_country.name).lower()
                if spanish_country == country_name:
                    if iso == 'alpha_3':
                        return english_country.alpha_3
                    elif iso == 'alpha_2':
                        return english_country.alpha_2
   
    except Exception as e:
        raise

Conversión de los nombres a códigos alpha

muestra_covid['alpha3'] = muestra_covid['pais_nacionalidad'].apply(lambda x: map_country_code(x, 'es', 'alpha_3'))
muestra_covid['alpha2'] = muestra_covid['pais_nacionalidad'].apply(lambda x: map_country_code(x, 'es', 'alpha_2'))
muestra_covid.head()
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  """Entry point for launching an IPython kernel.
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  
sexo edad entidad_nacimiento municipio_residencia indigena nacionalidad migrante pais_nacionalidad fecha_ingreso fecha_sintomas fecha_def municipio_residencia Lat_Decimal Lon_Decimal alpha3 alpha2
0 MUJER 75 QUERÉTARO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-02-21 2022-02-16 NaT naucalpan de juárez 19.478803 -99.233218 MEX MX
1 MUJER 32 CIUDAD DE MÉXICO naucalpan de juárez NO ESPECIFICADO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-07 2022-01-02 NaT naucalpan de juárez 19.478803 -99.233218 MEX MX
2 HOMBRE 30 CIUDAD DE MÉXICO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-02-04 2022-02-03 NaT naucalpan de juárez 19.478803 -99.233218 MEX MX
3 MUJER 51 CIUDAD DE MÉXICO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-01 2021-12-28 NaT naucalpan de juárez 19.478803 -99.233218 MEX MX
4 HOMBRE 83 GUANAJUATO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-01 2021-12-30 NaT naucalpan de juárez 19.478803 -99.233218 MEX MX

Guardar a CSV#

ruta = '/content/drive/MyDrive/Colab Notebooks/curso_datos/covid_clean.csv'
muestra_covid.to_csv(ruta, index=False)

comprobación

pd.read_csv(ruta)
sexo edad entidad_nacimiento municipio_residencia indigena nacionalidad migrante pais_nacionalidad fecha_ingreso fecha_sintomas fecha_def municipio_residencia.1 Lat_Decimal Lon_Decimal alpha3 alpha2
0 MUJER 75 QUERÉTARO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-02-21 2022-02-16 NaN naucalpan de juárez 19.478803 -99.233218 MEX MX
1 MUJER 32 CIUDAD DE MÉXICO naucalpan de juárez NO ESPECIFICADO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-07 2022-01-02 NaN naucalpan de juárez 19.478803 -99.233218 MEX MX
2 HOMBRE 30 CIUDAD DE MÉXICO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-02-04 2022-02-03 NaN naucalpan de juárez 19.478803 -99.233218 MEX MX
3 MUJER 51 CIUDAD DE MÉXICO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-01 2021-12-28 NaN naucalpan de juárez 19.478803 -99.233218 MEX MX
4 HOMBRE 83 GUANAJUATO naucalpan de juárez NO MEXICANA NO ESPECIFICADO MÉXICO 2022-01-01 2021-12-30 NaN naucalpan de juárez 19.478803 -99.233218 MEX MX
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
158080 HOMBRE 12 VERACRUZ DE IGNACIO DE LA LLAVE amatlán de los reyes NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-23 2022-06-23 NaN amatlán de los reyes 18.847578 -96.915484 MEX MX
158081 MUJER 46 CIUDAD DE MÉXICO amatlán de los reyes NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-22 2022-06-19 NaN amatlán de los reyes 18.847578 -96.915484 MEX MX
158082 MUJER 59 CIUDAD DE MÉXICO general simón bolívar NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-23 2022-06-22 NaN general simón bolívar 24.689074 -103.225975 MEX MX
158083 MUJER 27 MÉXICO temozón NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-24 2022-06-22 NaN temozón 20.803680 -88.201158 MEX MX
158084 MUJER 32 MÉXICO izamal NO MEXICANA NO ESPECIFICADO MÉXICO 2022-06-24 2022-06-20 NaN izamal 20.932998 -89.019715 MEX MX

158085 rows × 16 columns

Visualización de datos#

Importar las librerías necesarias:

!pip install plotly
import plotly.express as px
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Requirement already satisfied: plotly in /usr/local/lib/python3.7/dist-packages (5.5.0)
Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.7/dist-packages (from plotly) (8.0.1)
Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from plotly) (1.15.0)

Visualización de líneas#

Gráfico con los fallecimientos diarios totales en México durante el primer semestre de 2022:

  1. Preparación de los datos

ruta_datos = '/content/drive/MyDrive/Colab Notebooks/curso_datos/covid_clean.csv'
datos_covid = pd.read_csv(ruta_datos)
datos_covid['decesos'] = datos_covid['fecha_def'].apply(lambda x: 1 if pd.notnull(x) else 0)
muertes_diarias = datos_covid.groupby('fecha_def')['decesos'].sum().reset_index(name='fallecidos_diarios')
muertes_diarias.head()
fecha_def fallecidos_diarios
0 2022-01-03 2
1 2022-01-04 1
2 2022-01-05 2
3 2022-01-06 3
4 2022-01-07 7
  1. “Dibujar” el gráfico

fig = px.line(muertes_diarias, x='fecha_def', y='fallecidos_diarios')
fig.update_layout(
    title="Muertes diarias por COVID-19 en México",
    xaxis_title="Fecha",
    yaxis_title="Muertes diarias",
    font=dict(
        family="Roboto, monospace",
        size=18,
        color="#7f7f7f" # <-- el color de la fuente se puede definir con un código hexadecimal. Para conocer más sobre los códigos de colores, puedes consultar https://htmlcolorcodes.com/es/
    )
)
# color de línea y ancho
fig.update_traces(line_color='#ff7f0e', line_width=2)
fig.show()

Visualización de dispersión apilada (multigráfico)#

  1. Preparar la información. Un dataframe para cada gráfico:

hipertension = covid_nacional.loc[(covid_nacional['hipertension'] == 'SI') & (covid_nacional['fecha_def'].notnull())]
cardiovascular = covid_nacional.loc[(covid_nacional['cardiovascular'] == 'SI') & (covid_nacional['fecha_def'].notnull())]
renal_cronica = covid_nacional.loc[(covid_nacional['renal_cronica'] == 'SI') & (covid_nacional['fecha_def'].notnull())]
tabaquismo = covid_nacional.loc[(covid_nacional['tabaquismo'] == 'SI') & (covid_nacional['fecha_def'].notnull())]
  1. Agrupar cada dataframe:

# agrupar por edad y fecha de defunción
hipertension = hipertension.groupby(['edad', 'hipertension']).size().reset_index(name='count')
cardiovascular = cardiovascular.groupby(['edad', 'cardiovascular']).size().reset_index(name='count')
renal_cronica = renal_cronica.groupby(['edad', 'renal_cronica']).size().reset_index(name='count')
tabaquismo = tabaquismo.groupby(['edad', 'tabaquismo']).size().reset_index(name='count')
  1. Crear un gráfico de dispersión para cada grupo:

from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(rows=2, cols=2, subplot_titles=("Hipertensión", "Enfermedad cardiovascular", "Enfermedad renal crónica", "Tabaquismo"))
fig.add_trace(go.Scatter(x=hipertension['edad'], y=hipertension['count'], mode='markers'), row=1, col=1)
fig.add_trace(go.Scatter(x=cardiovascular['edad'], y=cardiovascular['count'], mode='markers'), row=1, col=2)
fig.add_trace(go.Scatter(x=renal_cronica['edad'], y=renal_cronica['count'], mode='markers'), row=2, col=1)
fig.add_trace(go.Scatter(x=tabaquismo['edad'], y=tabaquismo['count'], mode='markers'), row=2, col=2)
fig.update_layout(height=600, width=800, title_text="Relación entre edad, número de decesos y enfermedades preexistentes")

# actualizar los ejes
for i in range(1, 3):
    fig.update_yaxes(title_text="Número de decesos", row=1, col=i)
    fig.update_yaxes(title_text="Número de decesos", row=2, col=i)
    fig.update_xaxes(title_text="Edad", row=1, col=i)
    fig.update_xaxes(title_text="Edad", row=2, col=i)

fig.show()

Mapa#

Mapa de índices de incidencia (casos por cada 100,000 habitantes) en México durante el segundo semestre de 2022:

  1. Preparar los datos:

# recuperar los datos originales para evitar errores

casos_nacionales = pd.read_csv('/content/drive/MyDrive/Colab Notebooks/curso_datos/casos_nacionales_covid-19_2022_semestre1.csv')
geolocalizacion = pd.read_csv("/content/drive/MyDrive/Colab Notebooks/curso_datos/geolocalizacion.csv", encoding='utf-8')

# determinar casos por municipio de residencia

casos_nacionales = casos_nacionales['municipio_res'].value_counts().reset_index()
casos_nacionales.columns = ['municipio_res', 'casos']
casos_nacionales.rename(columns={'municipio_res': 'municipio_residencia'}, inplace=True)
casos_nacionales['municipio_residencia'] = casos_nacionales['municipio_residencia'].str.lower()
casos_nacionales = casos_nacionales.merge(geolocalizacion, on='municipio_residencia', how='left')

# limpieza de datos

casos_nacionales.drop(columns=['Unnamed: 0'], inplace=True)
casos_nacionales = casos_nacionales.dropna()

# agregar población total
areas = areas_inegi[['municipio_residencia', 'Lat_Decimal', 'Lon_Decimal', 'Pob_Total']]
areas['municipio_residencia'] = areas['municipio_residencia'].str.lower()
nuevodata = pd.merge(casos_nacionales, areas, on=['municipio_residencia', 'Lat_Decimal', 'Lon_Decimal'], how='inner')

# convertir Pob_Total a integral
nuevodata['Pob_Total'] = nuevodata['Pob_Total'].astype(int)

# calcular tasa de incidencia
nuevodata['tasa_incidencia'] = nuevodata['casos'] / nuevodata['Pob_Total'] * 100000

nuevodata.head()
/usr/local/lib/python3.7/dist-packages/IPython/core/interactiveshell.py:3326: DtypeWarning:

Columns (13) have mixed types.Specify dtype option on import or set low_memory=False.

/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:21: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
municipio_residencia casos Lat_Decimal Lon_Decimal Pob_Total tasa_incidencia
0 nezahualcóyotl 26282 19.408763 -99.018200 1072676 2450.134057
1 ecatepec de morelos 24107 19.599069 -99.049159 1643623 1466.698872
2 tlalnepantla de baz 17929 19.538523 -99.195198 658907 2721.021328
3 naucalpan de juárez 10020 19.478803 -99.233218 776220 1290.871145
4 chalco 6997 19.261132 -98.895655 174704 4005.059987
  1. Dibujar el mapa:

fig = px.scatter_mapbox(
    nuevodata, 
    lat="Lat_Decimal", 
    lon="Lon_Decimal",
    color='tasa_incidencia',
    size='tasa_incidencia',
    hover_name="municipio_residencia",
    hover_data=["casos", "Pob_Total", "tasa_incidencia"],
    color_continuous_scale=px.colors.cyclical.IceFire,
    size_max=50,
    zoom=4
    )

fig.update_layout(mapbox_style="open-street-map")
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})

fig.show()

Mapa animado#

Mapa animado del país de origen de los casos diarios de extranjeros:

  1. Preparar los datos:

# segmentar información para excluir casos mexicanos
mapa_extranjeros = muestra_covid.loc[muestra_covid['alpha3'] != 'MEX']

# limpiar datos que no se pudieron convertir
extranjeros = mapa_extranjeros.dropna(subset=['alpha3'])

# agrupar por pais_nacionalidad, alpha3 y alpha2
diario = extranjeros.groupby(['fecha_ingreso', 'pais_nacionalidad', 'alpha3', 'alpha2']).count().reset_index()

# renombrar columna sexo como casos
diario.rename(columns={'sexo': 'casos'}, inplace=True)

# eliminar columnas no necesarias
diario.drop(columns=['edad','entidad_nacimiento','municipio_residencia','indigena','nacionalidad','migrante', 'fecha_sintomas','fecha_def', 'Lat_Decimal', 'Lon_Decimal'], inplace=True)

# garantizar que fecha_ingreso sea datetime
diario['fecha_ingreso'] = diario['fecha_ingreso'].dt.strftime('%d/%m/%Y')

diario.head()
fecha_ingreso pais_nacionalidad alpha3 alpha2 casos
0 02/01/2022 REPÚBLICA DE COREA KOR KR 1
1 03/01/2022 ALEMANIA DEU DE 1
2 03/01/2022 COLOMBIA COL CO 1
3 03/01/2022 ECUADOR ECU EC 1
4 03/01/2022 ESTADOS UNIDOS DE AMÉRICA USA US 2
  1. Dibujar mapa

fig = px.choropleth(diario, locations="alpha3", color="casos", hover_name="pais_nacionalidad", projection="natural earth", animation_frame="fecha_ingreso", color_continuous_scale=px.colors.sequential.Plasma)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()

¿Qué aprendimos del Covid-19 con estos datos?#

Después del ejercicio de “machacar” los datos proporcionados por el gobierno de México, notamos que estamos llegando a una etapa de la pandemia mucho más controlada. Aunque los fallecimientos derivados de la enfermedad se incrementaron durante el mes de febrero, es claro que no alcanzó el nivel de meses críticos del año 2021 o 2020.

Los contagios fueron bastante altos en casi todas las poblaciones, mostrando que hay una concentración natural de contagios en el área del centro de México, donde se agrupa la mayor población del país. Aunque también es evidente una cantidad importante de casos en el norte del país, especialmente en los estados de Zacatecas, Nuevo León y Tamaulipas.

La cantidad de extranjeros que reportaron su contagio en México (esto no indica que se hayan infectado en el país o en el exterior) es significativa, con más de 10,000 casos, aunque la gran mayoría de estos se presentó con viajeros provenientes de Estados Unidos. No es por tanto factible en ningún caso considerar que la migración hacia o a través del país tenga correlación alguna con la distribución del virus.

Los datos no nos permiten corroborar la incidencia de las campañas de vacunación global en el apaciguamiento de la pandemia, pero no es descabellado adelantar tal hipótesis.

Sin duda una comparación de mayor calado (tomando los datos de 2019 hasta la fecha, por ejemplo) brindará mayores luces respecto al comportamiento de la pandemia en México.

Sigámonos cuidando 🙌