Skip to content

pandas pipe

Send a data frame through any function, without breaking the method chain.

pipe is the escape hatch that keeps chains intact. Pandas methods chain naturally because each returns a data frame — but the moment you need a function that isn't a Pandas method, the chain stops dead and you are back to temporary variables. pipe fixes that by handing your frame to any function you like and carrying on.

The clearest case is plotting, and it is where most people first meet the problem.

Official documentation: DataFrame.pipe

The problem it solves

Plotly Express takes the data frame as its first argument: px.line(df, x=..., y=...). That reads fine on its own, but it cannot be chained — there is no .px_line() method to call. So a chain that ends in a chart has to stop:

monthly = (
    df
    .set_index('time')
    .resample('ME')
    .agg(quakes=('mag', 'size'))
)
px.line(monthly)          # chain broken; a variable exists only to be used once

pipe passes the frame along as the first argument, so the chart becomes one more step:

(
    df
    .set_index('time')
    .resample('ME')
    .agg(quakes=('mag', 'size'))
    .pipe(px.line)
)

No monthly, no interruption. The chain reads top to bottom, ending in a picture.

The forms worth knowing

# The frame goes in as the first argument
df.pipe(px.line)

# Extra arguments pass straight through
df.pipe(px.bar, x='year', y='quakes', title='Earthquakes by month')
df.pipe(px.scatter, x='LON', y='LAT', color='WMO_WIND')

# Your own functions work the same way
df.pipe(clean_column_names)
df.pipe(add_per_capita, population=pop_df)

Two cases need more than the plain form.

When the frame is not the first parameter, name the parameter it should go to by passing a (function, 'argname') tuple:

df.pipe((some_function, 'data'), title='Chart')

When you need to reshape on the way in, use a lambda — this comes up with Series, where the plotting function wants values and labels separately:

series.pipe(lambda s_: px.pie(values=s_.values, names=s_.index))

That is the only reason to reach for a lambda here. If the frame goes in as the first argument, .pipe(px.line) says the same thing with less noise than .pipe(lambda df_: px.line(df_)).

A worked example, on real data

The USGS publishes every earthquake it records as CSV, through a public API with no key — the source Bamboo Weekly #3 worked with.

Load, bucket by month, aggregate, and plot — one expression:

import pandas as pd
from plotly import express as px

url = ('https://earthquake.usgs.gov/fdsnws/event/1/query.csv'
       '?starttime=2024-01-01&endtime=2024-12-31&minmagnitude=6')

(
    pd.read_csv(url, usecols=['time', 'mag'], parse_dates=['time'])
    .set_index('time')
    .resample('ME')
    .agg(quakes=('mag', 'size'),
         strongest=('mag', 'max'))
    .pipe(px.line)
)

That returns a Plotly figure with two traces — quakes and strongest — one point per month across 2024. Five steps, no intermediate names, and the whole analysis is readable as a single thought.

Add arguments when the defaults are not what you want:

(
    pd.read_csv(url, usecols=['time', 'mag'], parse_dates=['time'])
    .set_index('time')
    .resample('ME')
    .agg(quakes=('mag', 'size'))
    .reset_index()
    .pipe(px.bar, x='time', y='quakes',
          title='Magnitude 6+ earthquakes, 2024')
)

Three mistakes people make

Wrapping in a lambda when you do not need one. .pipe(lambda df_: px.line(df_)) and .pipe(px.line) do exactly the same thing, because pipe already passes the frame as the first argument. Save the lambda for when the frame has to go somewhere else.

Calling the function instead of naming it. df.pipe(px.line(df)) calls px.line yourself and then hands the result to pipe. Pass the function itself — df.pipe(px.line) — and let pipe do the calling.

Forgetting that pipe returns whatever the function returns. It is not obliged to give you a data frame back. .pipe(px.line) returns a Plotly figure, .pipe(len) returns an integer. That is the point — but it does mean a pipe step is usually the last one in the chain unless your function returns a frame.

Watch it

What the Pandas "pipe" method does covers this directly. For the wider style pipe completes, see Optimizing Pandas queries with method chaining and Method chaining in Pandas: Cleaner queries with assign, loc, and lambda.

Practice it

Work through a pipe exercise, with instant feedback and no signup required: practice.lernerpython.com/bamboo-weekly/pipe/

Go deeper

Bamboo Weekly is the practice. If you want the structured version — full courses with downloadable Jupyter notebooks, plus live Pandas office hours when you get stuck — that is LernerPython+Data. A paid Bamboo Weekly subscription is included with it.

See it on real data

Below are the 60 Bamboo Weekly exercises that use pipe on real-world data — try each one, then study the worked solution.

Part of the Pandas Methods Index. See also practice by skill.