Method Chaining & .pipe()

Method chaining is the practice of linking several pandas operations into one flowing expression, where each method returns a new DataFrame for the next to work on, so a whole cleaning pipeline reads as a single top-to-bottom story.

Learn Method Chaining & .pipe() in our free Pandas course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Pandas course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

You will chain dropna , assign , query , and sort_values , add columns with .assign() , drop in custom steps with .pipe() , and wrap chains in parentheses for clean formatting.

Most pandas methods return a new DataFrame rather than changing the original in place. That means the output of one method can flow straight into the next. Instead of a pile of df1 , df2 , df3 variables, you write a single chain that reads like a recipe.

.assign() returns a copy of the DataFrame with new columns added. You can add several at once, and a later column can build on one defined earlier in the same call by using a lambda . Because it never mutates in place, the original frame stays safe.

Sometimes a step is too custom for a built-in method. .pipe(func) passes the current DataFrame to func and returns whatever it gives back, so your own function reads like a native chain link. Without pipe you would have to break the chain to write func(df) .

Python ends the statement at the first newline:

✅ Fix: use a lambda so it sees the chained frame:

Turn a messy orders table into a tidy ranked result with a single chain.

Lesson complete — your pipelines read like prose!

You can chain dropna , assign , query , and sort_values , add columns with .assign() , slot custom steps in with .pipe() , and wrap it all in parentheses for clean formatting.

🚀 Up next: Styling & Formatting Output — make your tables look polished and readable.

Practice quiz

What makes method chaining possible in pandas?

  • Methods print as they run
  • Most methods return a new DataFrame for the next to act on
  • Methods always mutate in place
  • Pandas caches every step

Answer: Most methods return a new DataFrame for the next to act on. Each method returns a new DataFrame, so its output flows into the next call.

Why wrap a long chain in a pair of parentheses?

  • It runs faster
  • It is required by .pipe
  • So each method can sit on its own line without backslashes
  • It mutates the original

Answer: So each method can sit on its own line without backslashes. Python ignores line breaks inside parentheses, keeping the chain readable.

What does .assign() return?

  • None (mutates in place)
  • Only the new column
  • A new DataFrame with the column(s) added
  • A boolean mask

Answer: A new DataFrame with the column(s) added. .assign() returns a copy with the new columns, leaving the original untouched.

Inside a chain, why use assign(total=lambda d: ...) instead of assign(total=df[...])?

  • The lambda sees the current chained frame, not the original df
  • Lambdas are faster
  • df is undefined
  • It avoids parentheses

Answer: The lambda sees the current chained frame, not the original df. A lambda receives the current state of the chain; referencing df uses the original.

What does .query('total > 20') do in a chain?

  • Adds a column
  • Sorts the rows
  • Renames total
  • Filters rows where the condition is True

Answer: Filters rows where the condition is True. .query() keeps only rows matching the string expression.

When should you reach for .pipe(func)?

  • To insert your own function as a chain step
  • To sort values
  • To drop NaN
  • To rename columns

Answer: To insert your own function as a chain step. .pipe(func) passes the current frame to your function so a custom step reads like a native one.

Which method removes rows containing NaN inside a chain?

  • query()
  • dropna()
  • assign()
  • pipe()

Answer: dropna(). dropna() drops rows with missing values and returns a new frame.

What does df.pipe(my_func) pass to my_func?

  • Only the index
  • A copy of one column
  • The current DataFrame
  • Nothing

Answer: The current DataFrame. pipe hands the whole current DataFrame to your function as its first argument.

Why does line breaks WITHOUT parentheses break a chain?

  • Pandas disallows newlines
  • Python ends the statement at the first newline
  • It deletes the DataFrame
  • It raises a KeyError

Answer: Python ends the statement at the first newline. Without enclosing parentheses, Python treats the first line as the whole statement.

Which reads more clearly for three custom steps?

  • summarise(enrich(clean(df)))
  • Three separate scripts
  • df.pipe(clean).pipe(enrich).pipe(summarise)
  • A while loop

Answer: df.pipe(clean).pipe(enrich).pipe(summarise). Chained .pipe calls read top-to-bottom in order, unlike nested inside-out calls.