Encadenamiento de métodos con pipe()
Escriba pipelines legibles de transformación de datos usando pipe() para encadenar funciones personalizadas con métodos nativos de Pandas.
Encadenamiento de métodos con pipe() es una lección gratuita de Pandas & NumPy Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Pandas & NumPy Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Pandas & NumPy Academy incluye 4 lecciones en total.
El problema de las variables intermedias
Una canalización de limpieza de datos sin pipe() suele acumular muchas variables intermedias: df1 = clean(df), df2 = transform(df1), df3 = enrich(df2). Estas variables saturan el espacio de nombres, dificultan la depuración y pueden llevar a los desarrolladores a reutilizarlas incorrectamente. El resultado es un código difícil de leer de principio a fin como una secuencia de transformaciones.
import pandas as pd
df = pd.read_csv('orders.csv')
# Without pipe — intermediate variables everywhere
df1 = df.dropna(subset=['revenue'])
df2 = df1[df1['quantity'] > 0]
df3 = df2.assign(revenue_per_unit=df2['revenue'] / df2['quantity'])
print(df3.shape)Introducción a pipe()
DataFrame.pipe(func) llama a func(df) y devuelve el resultado, lo que permite encadenar funciones personalizadas del mismo modo que se encadenan métodos nativos de Pandas, como .dropna().query(). La principal ventaja es que cada paso de transformación queda explícito y es fácil de leer de izquierda a derecha, o de arriba abajo cuando se da formato con paréntesis, reflejando el orden lógico de la canalización.
def drop_nulls(df):
return df.dropna(subset=['revenue'])
def filter_positive_qty(df):
return df[df['quantity'] > 0]
def add_revenue_per_unit(df):
return df.assign(revenue_per_unit=df['revenue'] / df['quantity'])
# With pipe — clean chain
df_clean = (df
.pipe(drop_nulls)
.pipe(filter_positive_qty)
.pipe(add_revenue_per_unit)
)
print(df_clean.shape)Pasar argumentos mediante pipe()
Pase argumentos adicionales a la función canalizada mediante argumentos con nombre después del nombre de la función: df.pipe(func, arg1=val1). La firma de la función debe aceptar df como primer parámetro. Las funciones parametrizadas hacen que la canalización sea configurable: puede cambiar umbrales, nombres de columnas o comportamiento sin modificar el cuerpo de la función, simplemente cambiando los argumentos de la llamada a pipe.
def filter_by_region(df, regions):
return df[df['region'].isin(regions)]
def cap_revenue(df, upper):
df = df.copy()
df['revenue'] = df['revenue'].clip(upper=upper)
return df
df_result = (df
.pipe(filter_by_region, regions=['North', 'East'])
.pipe(cap_revenue, upper=1000)
)
print(df_result.shape)Combinar pipe() con métodos nativos
La potencia de pipe() reside en que se integra perfectamente con los métodos nativos de Pandas dentro de la misma cadena. Puede combinar .dropna(), .query(), .rename() y .pipe(custom_func) en cualquier orden. Esto hace que la cadena sea concisa (al utilizar métodos integrados siempre que sea posible) y flexible (al usar funciones personalizadas cuando los métodos integrados no son suficientes).
df_result = (
df
.dropna(subset=['revenue', 'order_date'])
.query('quantity > 0')
.rename(columns={'unit_price': 'price'})
.pipe(add_revenue_per_unit)
.reset_index(drop=True)
)
print(df_result.head())Depuración de una cadena con pipe()
Depurar una cadena larga puede ser complicado porque no puede inspeccionar los estados intermedios añadiendo una instrucción print en mitad de la cadena. Una solución consiste en escribir una función de depuración de paso directo que muestre información sobre las dimensiones y las columnas, y después devuelva el DataFrame sin modificarlo. Insértela en cualquier punto de la cadena para inspeccionar el estado en ese paso sin interrumpirla.
def debug(df, label=''):
print(f'[{label}] shape: {df.shape}')
print(f'[{label}] columns: {df.columns.tolist()}')
return df
df_result = (
df
.pipe(drop_nulls)
.pipe(debug, label='after drop_nulls')
.pipe(filter_positive_qty)
.pipe(debug, label='after filter')
)
print('Done')Creación de una canalización completa de limpieza
Combine todos los pasos de limpieza en una única función de canalización mediante pipe(). Envolver la cadena en una función llamada clean_pipeline(df) hace que la canalización se pueda probar como una unidad. Llámela con un DataFrame sin procesar y obtenga uno limpio. Este patrón sigue el paradigma ETL (Extract, Transform, Load), utilizado en la ingeniería de datos en producción.
def clean_pipeline(df):
return (
df
.dropna(subset=['order_id', 'revenue'])
.drop_duplicates(subset=['order_id'])
.query('quantity > 0 and revenue >= 0')
.pipe(add_revenue_per_unit)
.reset_index(drop=True)
)
df_clean = clean_pipeline(df)
print('Clean rows:', len(df_clean))pipe() frente a apply(): diferencias clave
pipe(func) pasa el DataFrame completo a func y espera recibir a cambio un DataFrame (u otro objeto transformado). apply(func, axis=1) pasa una fila cada vez. Use pipe() para transformaciones del DataFrame completo que mantengan la misma forma (o la cambien de manera intencionada), y use apply() para cálculos a nivel de fila o de columna. Son funciones complementarias, no competidoras.
# pipe: receives the whole DataFrame
def scale_revenue(df, factor=1.0):
df = df.copy()
df['revenue'] = df['revenue'] * factor
return df
# apply: receives one row at a time
df['revenue_x2'] = df.apply(lambda row: row['revenue'] * 2, axis=1)
df_scaled = df.pipe(scale_revenue, factor=1.1)
print('pipe scales all rows at once; apply does row-by-row')Componentes de canalización reutilizables
Escriba cada paso de la canalización como una función pura: sin estado global, recibe un DataFrame y devuelve un DataFrame. Las funciones puras son fáciles de probar mediante pruebas unitarias: llámelas con un DataFrame de prueba pequeño y compruebe la forma de la salida y los valores de las columnas. Una biblioteca de funciones de canalización probadas y reutilizables acelera considerablemente el análisis de nuevos conjuntos de datos que comparten requisitos de limpieza similares.
def normalise_strings(df, cols):
df = df.copy()
for col in cols:
df[col] = df[col].str.strip().str.lower()
return df
def parse_dates(df, cols):
df = df.copy()
for col in cols:
df[col] = pd.to_datetime(df[col])
return df
df_result = (
df
.pipe(normalise_strings, cols=['region', 'category'])
.pipe(parse_dates, cols=['order_date'])
)
print(df_result.dtypes)Registro de los pasos de la canalización con pipe()
Añada un registro estructurado dentro de cada función de la canalización para poder auditar todas las transformaciones en producción. Incluya el número de filas de entrada, el número de filas de salida y cualquier estadística relevante (por ejemplo, las filas eliminadas por un filtro). Así obtendrá un seguimiento completo de cada ejecución de la canalización sin necesitar un orquestador de flujos de trabajo externo para las trazas de auditoría básicas.
import logging
logging.basicConfig(level=logging.INFO)
def logged_dropna(df, subset):
before = len(df)
df = df.dropna(subset=subset)
after = len(df)
logging.info(f'dropna: {before - after} rows removed, {after} remaining')
return df
df_clean = df.pipe(logged_dropna, subset=['revenue'])
print('Logged pipeline complete.')Pasos condicionales en una canalización
En ocasiones, un paso de limpieza solo debe ejecutarse en función de un indicador o del contenido de los datos. Puede añadir pasos condicionales a una cadena de pipe insertando una función de identidad o transformación: comprueba una condición y aplica una transformación o devuelve el DataFrame sin modificarlo. Esto mantiene intacta la estructura de la cadena y permite incluir pasos opcionales.
def maybe_cap_revenue(df, cap=None):
if cap is None:
return df
df = df.copy()
df['revenue'] = df['revenue'].clip(upper=cap)
return df
CAPPING_ENABLED = True
CAP_VALUE = 1000 if CAPPING_ENABLED else None
df_result = df.pipe(maybe_cap_revenue, cap=CAP_VALUE)
print('Conditional step applied:', CAPPING_ENABLED)Exportación del resultado de la canalización
El último paso de una cadena de pipe() suele ser una exportación. Puede encadenar una función de exportación personalizada mediante pipe() o simplemente llamar al método nativo de exportación de Pandas después de la cadena. Usar un paso pipe(save_to_parquet) mantiene la exportación documentada como parte de la cadena y garantiza que siempre se ejecute sobre el DataFrame final ya limpio, no sobre una versión intermedia.
def save_parquet(df, path):
df.to_parquet(path, index=False)
print(f'Saved {len(df)} rows to {path}')
return df # return df so the chain can continue if needed
df_final = (
df
.pipe(clean_pipeline)
.pipe(save_parquet, path='orders_final.parquet')
)
print('Pipeline complete.')Comprobación rápida
Compruebe su comprensión de los conceptos de análisis de datos de esta lección.
Resumen de la lección
En esta lección ha aprendido: a usar pipe() para encadenar funciones personalizadas con métodos nativos de Pandas, a crear pasos de canalización reutilizables, parametrizados y comprobables como funciones puras, y a añadir registros de depuración y pasos condicionales dentro de una cadena de pipe. A continuación, exploraremos cómo estructurar los pasos de transformación como funciones para una canalización ETL de producción.
Aprende Python con un tutor de IA — gratis
Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.
- Cursos
- 30
- Lecciones
- 120
Preguntas frecuentes
¿La lección «Encadenamiento de métodos con pipe()» es gratis?
Sí — el texto completo de «Encadenamiento de métodos con pipe()» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Pandas & NumPy Academy, actualiza a CoddyKit PRO. El curso de Pandas & NumPy Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Encadenamiento de métodos con pipe()»?
Escriba pipelines legibles de transformación de datos usando pipe() para encadenar funciones personalizadas con métodos nativos de Pandas. Practicas Pandas & NumPy Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Pandas & NumPy Academy?
No se requiere experiencia previa. Pandas & NumPy Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Encadenamiento de métodos con pipe()»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Pandas & NumPy Academy?
Sí. Cada lección de Pandas & NumPy Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- apply() en columnas y filas
- apply() con GroupBy
- map() y applymap() para operaciones elemento a elemento
- Encadenamiento de métodos con pipe()