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.