10 Trucos en Pandas Que Hacen Su Trabajo Más Eficiente

Shiutang Li
May 01, 2020

Contents Outline

10 Trucos en Pandas Que Hacen Su Trabajo Más Eficiente

May 01, 2020 6 minutes read

Algunos comandos que usted ya conoce pero que no sabe que pueden ser usados de esta manera

Pandas es un paquete Python ampliamente utilizado para datos estructurados. Hay muchos tutoriales buenos de él, pero aquí todavía me gustaría introducir algunos trucos geniales que los lectores pueden no conocer antes y creo que son útiles.

read_csv

Todo el mundo conoce este comando. Pero los datos que intentas leer son grandes, intenta añadir este argumento: nrows = 5 para leer sólo en una pequeña porción de la tabla antes de cargar toda la tabla. Entonces podrías evitar el error eligiendo un delimitador equivocado (no siempre puede estar separado por una coma).

Photo from https://unsplash.com/

(O, puedes usar el comando 'head' en linux para comprobar las primeras 5 filas (digamos) en cualquier archivo de texto: head -n 5 data.txt (Gracias Ilya Levinson por señalar un error tipográfico aquí))

Luego, puedes extraer la lista de columnas usando df.columns.tolist() para extraer todas las columnas, y luego agregar el argumento usecols = ['c1', 'c2', ...] para cargar las columnas que necesites. Además, si conoces los tipos de datos de unas pocas columnas específicas, puedes añadir el argumento dtype = {'c1': str, 'c2': int, ...} para que se cargue más rápido. Otra ventaja de este argumento es que si tienes una columna que contiene tanto cadenas como números, es una buena práctica declarar su tipo como cadena, de modo que no obtendrás errores al intentar fusionar tablas usando esta columna como llave.


select_dtypes

Si el preprocesamiento de datos tiene que hacerse en Python, entonces este comando le ahorraría algo de tiempo. Después de leer en una tabla, los tipos de datos por defecto para cada columna podrían ser bool, int64, float64, object, category, timedelta64, o datetime64. Primero puedes comprobar la distribución por

df.dtypes.value_counts()
para conocer todos los tipos de datos posibles de su dataframe, entonces haga

df.select_dtypes(include=['float64', 'int64'])
para seleccionar un sub-dataframe con sólo características numéricas.


copy

Este es un comando importante si no has oído hablar de él ya. Si haces los siguientes comandos:

import pandas as pd
df1 = pd.DataFrame({ 'a':[0,0,0], 'b': [1,1,1]})
df2 = df1df2['a'] = df2['a'] + 1
df1.head()

Verás que el df1 está cambiado. Esto se debe a que df2 = df1 no está haciendo una copia de df1 y asignándola a df2, sino configurando un puntero que apunta a df1. Así que cualquier cambio en df2 resultaría en cambios en df1. Para arreglar esto, puedes hacer

df2 = df1.copy()
Ó

from copy import deepcopy
df2 = deepcopy(df1)

map

Este es un comando genial para hacer transformaciones de datos fáciles. Primero se define un diccionario en el que las " llaves" son los valores antiguos y los " valores" son los nuevos valores.

level_map = {1: 'high', 2: 'medium', 3: 'low'}
df['c_level'] = df['c'].map(level_map)

Algunos ejemplos: Verdadero, Falso a 1, 0 (para el modelado); definición de niveles; codificaciones léxicas definidas por el usuario.


apply or not apply?

Si quisiéramos crear una nueva columna con algunas otras columnas como entradas, aplicar la función sería bastante útil a veces.

def rule(x, y):
 if x == 'high' and y > 10:
      return 1
 else:
      return 0
df = pd.DataFrame({ 'c1':[ 'high' ,'high', 'low', 'low'], 'c2': [0, 23, 17, 4]})
df['new'] = df.apply(lambda x: rule(x['c1'], x['c2']), axis =  1)
df.head()

En los códigos anteriores, definimos una función con dos variables de entrada, y usamos la función de apply para aplicarla a las columnas "c1" y "c2".

pero el problema de "apply" es que a veces es demasiado lenta. Digamos que si quieres calcular el máximo de dos columnas "c1" y "c2", por supuesto puedes hacer


df['maximum'] = df.apply(lambda x: max(x['c1'], x['c2']), axis = 1)
pero lo encontrarás mucho más lento que este comando:

df['maximum'] = df[['c1','c2']].max(axis =1)

Para llevar: No uses apply si puedes hacer el mismo trabajo con otras funciones incorporadas (a menudo son más rápidas). Por ejemplo, si quieres redondear la columna 'c' a números enteros, haz round(df['c'], 0) o df['c'].round(0) en lugar de usar la función apply: df.apply(lambda x: round(x['c'], 0), axis = 1).


value counts

Este es un comando para comprobar las distribuciones de valor. Por ejemplo, si quieres comprobar cuáles son los posibles valores y la frecuencia de cada valor individual en la columna "c" puedes hacer

df['c'].value_counts()

Hay algunos trucos y argumentos útiles:

A. normalize = True: si quieres comprobar la frecuencia en lugar de los recuentos.

B. dropna = False: si también quieres incluir los valores que faltan en las estadísticas.

C. df['c'].value_counts().reset_index(): si quieres convertir la tabla de estadísticas en un dataframe de pandas y manipularlo

D. df['c'].value_counts().reset_index().sort_values(by='index') : muestra las estadísticas ordenadas por distintos valores en la columna 'c' en lugar de los recuentos.

(Actualización 2019.4.18 - para D. arriba, Hao Yang señala una forma más simple sin .reset_index(): df['c'].value_counts().sort_index())


Número de valores perdidos

Cuando se construyen modelos, puede que quieras excluir la fila con demasiados valores perdidos / las filas con todos los valores perdidos. Puede utilizar .isull() y .sum() para contar el número de valores perdidos dentro de las columnas especificadas.


import pandas as pd
import numpy as np

df = pd.DataFrame({ 'id': [1,2,3], 'c1':[0,0,np.nan], 'c2': [np.nan,1,1]})
df = df[['id', 'c1', 'c2']]
df['num_nulls'] = df[['c1', 'c2']].isnull().sum(axis=1)
df.head()


Seleccionar filas con identificaciones específicas

En SQL podemos hacer esto usando SELECT * FROM ... WHERE ID in ('A001', 'C022', ...) para obtener registros con IDs específicos. Si quieres hacer lo mismo con pandas, puedes hacerlo


df_filter = df['ID'].isin(['A001','C022',...])
df[df_filter]


Grupos de percentiles

Tienes una columna numérica, y te gustaría clasificar los valores de esa columna en grupos, digamos el 5% superior en el grupo 1, 5-20% en el grupo 2, 20%-50% en el grupo 3, 50% inferior en el grupo 4. Por supuesto, puedes hacerlo con pandas.cut, pero me gustaría proporcionar otra opción aquí:

import numpy as np
cut_points = [np.percentile(df['c'], i) for i in [50, 80, 95]]
df['group'] = 1
for i in range(3):
    df['group'] = df['group'] + (df['c'] < cut_points[i])
# or <= cut_points[i]

que es más rápido de ejecutar (no se utiliza la función apply).


to_csv

De nuevo, este es un comando que todos usarían. Me gustaría señalar dos trucos aquí. El primero es


print(df[:5].to_csv())


Puedes usar este comando para imprimir las primeras cinco filas de lo que se va a escribir en el archivo exactamente.

Otro truco es tratar con números enteros y valores perdidos mezclados. Si una columna contiene tanto valores perdidos como enteros, el tipo de datos seguiría siendo float en lugar de int. Cuando se exporta la tabla, se puede añadir float_format='%.0f' para redondear todos los floats a enteros. Usa este truco si sólo quieres salidas de enteros para todas las columnas - te librarás de todos los molestos '.0's.


Join our private community in Discord

Keep up to date by participating in our global community of data scientists and AI enthusiasts. We discuss the latest developments in data science competitions, new techniques for solving complex challenges, AI and machine learning models, and much more!