Reto Usando Pandas Profiling Para Acelerar Nuestra Exploración de Datos

Pandas Profiling es una librería que genera informes desde un DataFrame de pandas. La función pandas df.describe() que usamos normalmente en Pandas es genial pero es un poco básica para un análisis exploratorio de datos más serio y detallado. pandas_profiling extiende el pandas DataFrame con df.profile_report() para un análisis de datos rápido.

Se presenta en un informe interactivo las siguientes estadísticas para cada columna.

Para este Reto vas a user el dataset que se encuentra en el siguiente link: Caida de meteoritos

Este completo conjunto de datos de la Sociedad Meteorológica contiene información sobre todos los aterrizajes de meteoritos conocidos. Es interesante observar los lugares de la tierra donde han caido estos objetos, siguiendo las coordenadas del dataset.

Mapa de caidas de meteoritos

Screenshot%20from%202020-11-10%2007-22-17.png

Comencemos ahora importando el dataset, para poder entender un poco los datos que trabajaremos. Primer importa pandas en la siguiente celda

Guarda el dataset (Caida de meteoritos) en la carpeta datasets del presente entorno de trabajo, e importa el dataset en la siguiente celda

Y ahora revisa los datos con la funcion .head() y .shape de Pandas

Es un dataset muy interesante, donde podemos observar el nombre que los científicos le dieron al meteorito, el tipo de clase recclass, el peso en gramos mass (g) la fecha en la que cayó y las coordenadas en las cuales cayó.

También es importante notar que se trata de un dataset muy completo, con 45.716 registros y 10 columnas. Esta información es dada por el .shape

Para más información sobre el dataset puedes ingresar aqui: Meteoritos - Nasa

Ahora, como mencionamos al principio, con Pandas nos hemos acostumbrado a correr el comando .describe() para generar un análisis descriptivo sobre el dataset en cuestión. Las estadísticas descriptivas incluyen las que resumen la tendencia central, la dispersión y la forma de la distribución de un conjunto de datos, excluyendo los valores NaN.

Analiza tanto series numéricas como de objetos, así como conjuntos de columnas DataFrame de tipos de datos mixtos. El resultado variará en función de lo que se proporcione. Para más información sobre .describe() y los parámetros que podemos pasar, aqui puede encontrar la info: Pandas describe

Ahora corre el comando .describe() de Pandas sobre el dataframe y revisa el resultado

El describe omite las columnas categoricas (tipo string) y hace un análisis estadístico descriptivo sobre las columnas numéricas. Aquí podríamos ver que la columna id podria no ser util para este analisis, ya que se trata solamente de un indicador unico para cada fila (llave primaria de la tabla), mientras que la masa si es útil e interesante entender, por ejemplo, el valor minimo y maximo, la media y los percentiles (25, 50, 75).

Como vemos, se trata de un análisis muy básico, sin más información relevante. Si queremos información más relevante debemos empezar a escribir código.

Aqui es donde viene Pandas profiling, y su utilidad. La documentación de esta librería la puedes encontrar en el siguiente enlace. Pandas profiling. La instalación la haremos de la siguiente manera

Instalando e importando Pandas Profiling

Instala la libreria en la siguiente celda con este comando

!pip3 install 'pandas-profiling[notebook,html]'

Es obligatorio pasar entre comillas el comando y seguido de notebook,html esto es debido a que necesitaremos estas dos funciones de la librearía.

Si estás usando Conda, estas son las otras formas de instalarlo: Instalando Pandas profiling

Creando columnas relevantes para el análisis

Ahora vamos a crear una serie de columnas que serán relevantes para el analisis que haremos con Pandas Profiling, la primera de ellas sera crear una variable constante para todos los registros, en esta ocasión diremos que todos los registros pertenecen a la NASA, asi que crea una nueva columna llamada source y asignale el valor de NASA a todas las filas y revisa con el .head() que se haya creado

Como vemos, al final se creó dicha columna. Vamos a crear ahora una variable booleana de forma aleatoria, simulando algún tipo de salida booleana para cada registro.

Recordemos que esto se hace con el fin de que nuestro análisis exploratorio pueda identificar este tipo de datos en el resultado.

Instala e importa numpy

crea una nueva columna llamada boolean y asignale el siguiente random de numpy: np.random.choice([True, False], df.shape[0]). Numpy nos va a ayudar a crear esos booleanos aleatorios

Como vemos se creo la columna boolean con valores aleatorios de True o False para cada una de las filas de nuestro dataset, esto es gracias al df.shape[0] que hace referencia a las filas o registros del dataset, o sea que hizo esta operación 45.716 veces, el cual es el numero total de registros.

Hagamos ahora algo similar, pero mezclando tipos de datos numéricos y tipos de datos categóricos (strings). Crea una columna llamada mixed y asigname este random: np.random.choice([1, 'A'], df.shape[0])

Como vemos, aqui estamos simulando que una columna tiene dos tipos de datos mezclados, tanto numericos como categoricos. Esto es algo que podemos encontrar en los datasets reales, y describe() de Pandas simplemente los va a ignorar, y no nos dará ningun analisis sobre esa columna (recuerden que describe() solo arroja resultados sobre columnas numéricas, incluso ignora también las columnas booleanas)

Vamos ahora a hacer algo más interesante aún. Vamos a crear una nueva columna simulando una alta correlación con una columna existente. Particularmente lo haremos sobre la columna reclat que habla de la latitud donde ha caido el meteorito, y le sumamos una distribución normal con una desviación estandar de 5 y de un tamaño de muestras igual a la longitud del dataset.

Si quieres ver como se crea una simulación de una distribucion normal con numeros aleatorios, revisa este link. Random normal numpy

Para este punto crea una nueva columna llamada reclat_city y haz la siguiente operacion: seleccion y suma la columna llamada reclat al siguiente random: np.random.normal(scale=5, size=(len(df)))

Revisemos el resultado del último comando, podemos ver que esta columna reclat_city ahora tiene una alta correlacion con reclat, porque cuando una observación o fila es positiva la otra también, y cuando una es negativa, la otra también.

Para analizar correlaciones con Pandas usamos un método diferente al describe(), en este caso usamos el comando corr(). Sin embargo, con Pandas profiling ambos análisis (estadística descriptiva y correlaciones) los obtendremos con un solo comando. Lo veremos en unos momentos cuando corramos nuestro análisis exploratorio.

Recuerden que por ahora lo que estamos haciendo es añadiendo columnas al dataframe con el fin de ver todas las posibilidades que nos ofrece la herramienta de Pandas profiling.

Vamos a simular ahora otro escenario común en los datasets, y es tener observaciones o filas duplicadas. Crea un nuevo dataframe de pandas con los siguientes datos df.iloc[0:10] y asignalo a una variable llamada duplicates_to_add

Lo que acabamos de hacer fue crear un nuevo dataframe a partir de las 10 primeras filas de nuestro dataframe original. Para ello usamos un iloc que sirve para seleccionar filas y un selector tipo slice para seleccionar de la fila cero a la fila 10-1.

Ahora cambiemos el nombre para identificarlas posteriormente, pero los demás valores quedan igual, crea una nueva columna llamada name para el dataframe duplicates_to_add, y asignale este valor: duplicates_to_add['name'] + " copy"

Si vemos, ahora todos los nombres tienen la plabra copy al final. Ya tenemos este nuevo dataset listo para concatenarlo al dataset original, y asi poder tener datos duplicados. Ahora realiza un .append entre df y duplicates_to_add, no te olvides de pasar el parametro ignore_index=True y finalmente vuelve a ejecutar el comando .shape para confirmar el numero de filas y columna, que hasta el momento deberia ser (45726, 14)

El dataset original contiene 45716 filas, ahora tenemos 10 filas más, que son las filas duplicadas. De hecho podemos ver algunas de ellas en la visualización anterior!

Usando Pandas profiling

Ahora si hemos llegado al momento esperado, hemos añadido unas columnas al dataset que permitirán ver análisis interesantes sobre él. Pero antes de ello, debemos ser justos con el pandas describe() y mirar que análisis nos entrega sobre el dataset resultante. Por tanto corre describe() sobre el df

Como vemos, muy poca diferencia, no nos entrega información adicional sobre:

Aquí es donde Pandas profiling brilla por su sencillez para realizar un análisis exploratorio sobre nuestros datasets. Sin más corramos los siguientes comandos para importar pandas profiling:

import pandas_profiling
from pandas_profiling.utils.cache import cache_file

Los reportes de pandas profiling se corren de la siguiente forma .profile_report(sort='None', html={'style':{'full_width':True}}) sobre el dataframe df. Hazlo y asigna el resultado a la variable report

Interpretando los resultados

La salida habla por si sola. En comparación con Pandas describe() o incluso con Pandas corr() es bastante significativa, y de entrada podemos observar un montón de datos y análisis adicionales que nos ayadarán a interpretar mejor el dataset con el cual estamos trabajando. analicemos por ejemplo las columnas que recientemente agregamos

Para más un análisis más detallado sobre los resultados obtenidos con este dataset usando Pandas profiling, porfaor vaya a este link. ¿Cómo Usar Pandas Profiling Para Análisis Exploratorio de Datos?

Finalmente podríamos querer tener este informe en un formato diferente a un Jupyter Notebook, la librería nos ofrece la posibilidad de exportar el informe a html, lo cuál es útil para mostrarlo en un ambiente más amigable para el usuario final. En el cual puede incluso interactuar por medio de barras de navegación. Esto se hace con el método .to_file(output_file="folder_name/file_name.html") y corriendolo sobre el report. Hazlo en la siguiente celda

El archivo en este caso ha quedado dentro de mi ambiente de trabajo

Screenshot%20from%202020-11-10%2009-14-00.png

Si le damos click se abrirá en el navegador. Este formato, personalmente me gusta bastante, ya que no influye el código, sino que se puede navegar a traves del análisis y mostrarlo a los stackeholders interesados en el análisis y tomar decisiones con base en ellos.

Screenshot%20from%202020-11-10%2009-14-12.png

Notas finales

Como ven, es muy facil de utilizar la herramienta, y es un primer paso antes de empezar a realizar feature engineering y predicciones. Sin embargo existen algunas desventajas sobre la herramienta que son importantes tenerlo en cuenta:

Eejecuta el metodo .sample de pandas sobre el dataframe llamado df y asignale un parametro con un total de 1.000 muestras asi n=1000. Finalmente asigna esta operación a una nueva variable llamada data. En otra celda verifica el lenght de data

Como vemos se han seleccionado 1000 muestras al azar, por tanto no hará el análisis sobre más de 40.000 muestras. Si tenemos, digamos 1.000.000 de muestras, la diferencia en rendimiento será notable, por ello esta sería una buena práctica. Vuelve a correr el .profile_report pero esta vez sobre data

Como vemos toma menos tiempo de ejecutarse con una muestra de 1.000 ejemplos.

Como podemos ver, es un reporte más rápido pero con menos información sobre el análsis exploratorio de los datos. Dejámos a tu disposición la decisión sobre el tipo de informe que quieres generar. Si quieres ver funcionalidades más avanzadas de la librería porfavor dirijete al siguiente link: Pandas profiling avanzado

Esperamos te haya gustado este Reto, nos vemos en el próximo!