Reshaping Data with stack() and unstack() in Pandas

1. Introduction

While melt() and pivot reshape DataFrames between wide and long formats, Pandas also provides stack() and unstack() for reshaping MultiIndex DataFrames.

  • stack() → compresses a level of column labels into rows.
  • unstack() → expands a level of row index into columns.

These operations are extremely useful when working with hierarchical indices in Pandas.


2. Example Dataset

import pandas as pd

data = {
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Math': [85, 90, 95],
    'Science': [88, 92, 96],
    'English': [80, 85, 89]
}

df = pd.DataFrame(data)
df = df.set_index('Name')  # Make Name the index
print(df)

Output:

         Math  Science  English
Name                           
Alice      85       88       80
Bob        90       92       85
Charlie    95       96       89

3. Using stack()

stacked = df.stack()
print(stacked)

Output:

Name          
Alice    Math       85
         Science    88
         English    80
Bob      Math       90
         Science    92
         English    85
Charlie  Math       95
         Science    96
         English    89
dtype: int64

👉 Notice how the columns collapsed into a row index, creating a MultiIndex Series.


4. Using unstack()

unstacked = stacked.unstack()
print(unstacked)

Output:

         English  Math  Science
Name                           
Alice         80    85       88
Bob           85    90       92
Charlie       89    95       96

👉 The unstack() reversed the effect of stack().


5. Controlling Levels in MultiIndex

Let’s extend our dataset by creating a hierarchical index:

data = {
    'Class': ['A', 'A', 'B', 'B'],
    'Name': ['Alice', 'Bob', 'Charlie', 'David'],
    'Math': [85, 90, 88, 76],
    'Science': [88, 92, 84, 80]
}

df = pd.DataFrame(data)
df = df.set_index(['Class', 'Name'])
print(df)

Output:

             Math  Science
Class Name                  
A     Alice    85       88
      Bob      90       92
B     Charlie  88       84
      David    76       80

Stack the columns

stacked = df.stack()
print(stacked)

Output:

Class  Name    
A      Alice    Math       85
                Science    88
       Bob      Math       90
                Science    92
B      Charlie  Math       88
                Science    84
       David    Math       76
                Science    80
dtype: int64

Unstack at different levels

unstacked = stacked.unstack(level=-1)  # Last level
print(unstacked)

Output:

             English  Math  Science
Class Name                          
A     Alice         NaN    85       88
      Bob           NaN    90       92
B     Charlie       NaN    88       84
      David         NaN    76       80

6. Summary

  • stack() → turns columns into rows.
  • unstack() → turns row index into columns.
  • Works best with MultiIndex DataFrames.
  • Useful for reshaping data in hierarchical structures.

Yes — the Seaborn datasets are great for demonstrating stack() and unstack(). Let me show you using e.g. the Titanic and Tips datasets. I’ll write example code + explain what happens.


🔍 Examples with Seaborn’s Titanic & Tips

import pandas as pd
import seaborn as sns

# Load Titanic
titanic = sns.load_dataset('titanic')
print(titanic.head(5))

Example 1: Titanic — unstack after grouping

# Group Titanic by Pclass and Survived, count numbers
grouped = titanic.groupby(['pclass', 'survived']).size()
print(grouped.head())

# Unstack survived so that survived values become columns
unstacked = grouped.unstack()  
print(unstacked)
  • Here, grouped is a Series with MultiIndex (levels: pclass, survived).
  • unstack() converts one level of the row index (survived) to columns.
  • Result: rows = pclass, columns = survived (0,1).
  • Useful to see how many survived vs not in each passenger class.

Example 2: Titanic — stack back

stacked_back = unstacked.stack()
print(stacked_back)
  • This takes the unstacked DataFrame and turns the “survived” column level back into a row-level index.
  • You essentially get back the grouped Series (with MultiIndex).

Example 3: Using Tips dataset with pivot, then stack/unstack

tips = sns.load_dataset('tips')
print(tips.head(5))

Suppose you want counts of “day” vs “sex”:

counts = tips.groupby(['day', 'sex']).size().unstack()
print(counts)
  • Rows: days (Thur, Fri, Sat, Sun)
  • Columns: sexes (Male, Female) with counts

Then stack:

stacked_counts = counts.stack()
print(stacked_counts)
  • This moves the sex column level back into the index, giving back a Series with MultiIndex (day, sex).

✅ Why these are useful

  • unstack() is good for turning a groupby result into a “cross-tab” or pivot-table–like layout, where one categorical variable becomes columns.
  • stack() is the inverse, helpful when you need a tidy long format (e.g. for plotting, or further processing).
  • With Titanic & Tips datasets, there are many categorical columns, so stacking/unstacking helps you reshape.


Reshaping Data with stack() and unstack() in Pandas

1. Introduction

While melt() and pivot reshape DataFrames between wide and long formats, Pandas also provides stack() and unstack() for reshaping MultiIndex DataFrames.

  • stack() → compresses a level of column labels into rows.
  • unstack() → expands a level of row index into columns.

These operations are extremely useful when working with hierarchical indices in Pandas.


2. Example Dataset

import pandas as pd

data = {
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Math': [85, 90, 95],
    'Science': [88, 92, 96],
    'English': [80, 85, 89]
}

df = pd.DataFrame(data)
df = df.set_index('Name')  # Make Name the index
print(df)

Output:

         Math  Science  English
Name                           
Alice      85       88       80
Bob        90       92       85
Charlie    95       96       89

3. Using stack()

stacked = df.stack()
print(stacked)

Output:

Name          
Alice    Math       85
         Science    88
         English    80
Bob      Math       90
         Science    92
         English    85
Charlie  Math       95
         Science    96
         English    89
dtype: int64

👉 Notice how the columns collapsed into a row index, creating a MultiIndex Series.


4. Using unstack()

unstacked = stacked.unstack()
print(unstacked)

Output:

         English  Math  Science
Name                           
Alice         80    85       88
Bob           85    90       92
Charlie       89    95       96

👉 The unstack() reversed the effect of stack().


5. Controlling Levels in MultiIndex

Let’s extend our dataset by creating a hierarchical index:

data = {
    'Class': ['A', 'A', 'B', 'B'],
    'Name': ['Alice', 'Bob', 'Charlie', 'David'],
    'Math': [85, 90, 88, 76],
    'Science': [88, 92, 84, 80]
}

df = pd.DataFrame(data)
df = df.set_index(['Class', 'Name'])
print(df)

Output:

             Math  Science
Class Name                  
A     Alice    85       88
      Bob      90       92
B     Charlie  88       84
      David    76       80

Stack the columns

stacked = df.stack()
print(stacked)

Output:

Class  Name    
A      Alice    Math       85
                Science    88
       Bob      Math       90
                Science    92
B      Charlie  Math       88
                Science    84
       David    Math       76
                Science    80
dtype: int64

Unstack at different levels

unstacked = stacked.unstack(level=-1)  # Last level
print(unstacked)

Output:

             English  Math  Science
Class Name                          
A     Alice         NaN    85       88
      Bob           NaN    90       92
B     Charlie       NaN    88       84
      David         NaN    76       80

6. Summary

  • stack() → turns columns into rows.
  • unstack() → turns row index into columns.
  • Works best with MultiIndex DataFrames.
  • Useful for reshaping data in hierarchical structures.

Yes — the Seaborn datasets are great for demonstrating stack() and unstack(). Let me show you using e.g. the Titanic and Tips datasets. I’ll write example code + explain what happens.


🔍 Examples with Seaborn’s Titanic & Tips

import pandas as pd
import seaborn as sns

# Load Titanic
titanic = sns.load_dataset('titanic')
print(titanic.head(5))

Example 1: Titanic — unstack after grouping

# Group Titanic by Pclass and Survived, count numbers
grouped = titanic.groupby(['pclass', 'survived']).size()
print(grouped.head())

# Unstack survived so that survived values become columns
unstacked = grouped.unstack()  
print(unstacked)
  • Here, grouped is a Series with MultiIndex (levels: pclass, survived).
  • unstack() converts one level of the row index (survived) to columns.
  • Result: rows = pclass, columns = survived (0,1).
  • Useful to see how many survived vs not in each passenger class.

Example 2: Titanic — stack back

stacked_back = unstacked.stack()
print(stacked_back)
  • This takes the unstacked DataFrame and turns the “survived” column level back into a row-level index.
  • You essentially get back the grouped Series (with MultiIndex).

Example 3: Using Tips dataset with pivot, then stack/unstack

tips = sns.load_dataset('tips')
print(tips.head(5))

Suppose you want counts of “day” vs “sex”:

counts = tips.groupby(['day', 'sex']).size().unstack()
print(counts)
  • Rows: days (Thur, Fri, Sat, Sun)
  • Columns: sexes (Male, Female) with counts

Then stack:

stacked_counts = counts.stack()
print(stacked_counts)
  • This moves the sex column level back into the index, giving back a Series with MultiIndex (day, sex).

✅ Why these are useful

  • unstack() is good for turning a groupby result into a “cross-tab” or pivot-table–like layout, where one categorical variable becomes columns.
  • stack() is the inverse, helpful when you need a tidy long format (e.g. for plotting, or further processing).
  • With Titanic & Tips datasets, there are many categorical columns, so stacking/unstacking helps you reshape.