Examples
Single level columns:

In [1]:
import numpy as np
import pandas as pd
In [2]:
df_single_level_cols = pd.DataFrame([[0, 2], [3, 4]],
                                    index=['deer', 'monkey'],
                                    columns=['weight', 'height'])

Stacking a dataframe with a single level column axis returns a Series:

In [3]:
df_single_level_cols
Out[3]:
weight height
deer 0 2
monkey 3 4

Pandas: DataFrame - Stack Single level column.

In [4]:
df_single_level_cols.stack()
Out[4]:
deer    weight    0
        height    2
monkey  weight    3
        height    4
dtype: int64

Pandas: DataFrame - Stacking a dataframe with a single level column axis returns a Series.

Multi level columns: simple case:

In [5]:
multicol1 = pd.MultiIndex.from_tuples([('weight', 'kg'),
                                       ('weight', 'pounds')])
df_multi_level_cols1 = pd.DataFrame([[3, 4], [4, 5]],
                                    index=['deer', 'monkey'],
                                    columns=multicol1)

Stacking a dataframe with a multi-level column axis:

In [6]:
df_multi_level_cols1
Out[6]:
weight
kg pounds
deer 3 4
monkey 4 5

Pandas: DataFrame - Stacking a dataframe with a multi-level column axis.

In [7]:
df_multi_level_cols1.stack()
Out[7]:
weight
deer kg 3
pounds 4
monkey kg 4
pounds 5

Pandas: DataFrame - Stacking a dataframe with a multi-level column axis.

Missing values

In [8]:
multicol2 = pd.MultiIndex.from_tuples([('weight', 'kg'),
                                       ('height', 'm')])
df_multi_level_cols2 = pd.DataFrame([[2.0, 3.0], [4.0, 5.0]],
                                    index=['deer', 'monkey'],
                                    columns=multicol2)

It is common to have missing values when stacking a dataframe with multi-level columns,
as the stacked dataframe typically has more values than the original dataframe. Missing values
are filled with NaNs:

In [9]:
df_multi_level_cols2
Out[9]:
weight height
kg m
deer 2.0 3.0
monkey 4.0 5.0

Pandas: DataFrame - Missing values stacking a dataframe with multi-level column.

In [10]:
df_multi_level_cols2.stack()
Out[10]:
height weight
deer kg NaN 2.0
m 3.0 NaN
monkey kg NaN 4.0
m 5.0 NaN

Pandas: DataFrame - Missing values are filled with NaNs.

Prescribing the level(s) to be stacked:
The first parameter controls which level or levels are stacked:

In [11]:
df_multi_level_cols2.stack(0)
Out[11]:
kg m
deer height NaN 3.0
weight 2.0 NaN
monkey height NaN 5.0
weight 4.0 NaN

Pandas: DataFrame - The first parameter controls which level or levels are stacked.

In [12]:
df_multi_level_cols2.stack([0, 1])
Out[12]:
deer    height  m     3.0
        weight  kg    2.0
monkey  height  m     5.0
        weight  kg    4.0
dtype: float64

Pandas: DataFrame - The first parameter controls which level or levels are stacked.

Dropping missing values:

In [13]:
df_multi_level_cols3 = pd.DataFrame([[None, 2.0], [3.0, 4.0]],
                                    index=['deer', 'monkey'],
                                    columns=multicol2)

Note that rows where all values are missing are dropped by default but this behaviour
can be controlled via the dropna keyword parameter:

In [14]:
df_multi_level_cols3
Out[14]:
weight height
kg m
deer NaN 2.0
monkey 3.0 4.0

Pandas: DataFrame - rows where all valkues are missing are dropped by default .

In [15]:
df_multi_level_cols3.stack(dropna=False)
Out[15]:
height weight
deer kg NaN NaN
m 2.0 NaN
monkey kg NaN 3.0
m 4.0 NaN

Pandas: DataFrame - dropna=false value.

In [16]:
df_multi_level_cols3.stack(dropna=True)
Out[16]:
height weight
deer m 2.0 NaN
monkey kg NaN 3.0
m 4.0 NaN

Pandas: DataFrame - dropna=true value.