stack() moves column labels down into the index, producing a Series, for a simple DataFrame, or a DataFrame with a MultiIndex, where each combination of the original row label and column label becomes its own row — conceptually similar to melt(), but working at the index/columns structural level rather than reshaping via specific column names, and it's specifically designed to pair with hierarchical (MultiIndex) columns. By default, dropna=True drops any resulting rows that would be entirely NaN, which is common after stacking a DataFrame that had some genuinely missing cells.
1Understanding df.stack()
stack() moves column labels down into the index, producing a Series, for a simple DataFrame, or a DataFrame with a MultiIndex, where each combination of the original row label and column label becomes its own row — conceptually similar to melt(), but working at the index/columns structural level rather than reshaping via specific column names, and it's specifically designed to pair with hierarchical (MultiIndex) columns. By default, dropna=True drops any resulting rows that would be entirely NaN, which is common after stacking a DataFrame that had some genuinely missing cells.
stack() and unstack() are exact inverses of each other — stack() moves the innermost column level down into the index, and unstack() moves the innermost index level back up into columns, so applying one immediately after the other, when nothing else changes in between, returns you to the original shape.
import pandas as pd
df = pd.DataFrame({"math": [90, 85], "science": [95, 80]}, index=["Alice", "Bob"])
print(df.stack())2Practical Example
Here is a real-world application of df.stack() showing how it is used in production Pandas code.
import pandas as pd
df = pd.DataFrame({"math": [90, 85]}, index=["Alice", "Bob"])
stacked = df.stack()
unstacked = stacked.unstack()
print(unstacked.equals(df))3Best Practices
Follow these guidelines when working with df.stack():
1. Use stack() when you specifically need to work with hierarchical (MultiIndex) columns, converting them into an equally hierarchical row index
2. Pass dropna=False if entirely-NaN rows produced by stacking sparse data should be kept rather than silently dropped
3. Reach for melt() instead of stack() when the reshaping is more naturally described by specific column names rather than the index/columns structure itself
Tip: stack() and unstack() are exact inverses of each other — stack() moves the innermost column level down into the index, and unstack() moves the innermost index level back up into columns, so applying one immediately after the other, when nothing else changes in between, returns you to the original shape.
import pandas as pd
df = pd.DataFrame({"math": [90, 85], "science": [95, 80]}, index=["Alice", "Bob"])
print(df.stack())