Pandas MultiIndex

MultiIndex is a powerful indexing feature in Pandas that allows creating multi-level hierarchical structures on rows or columns. This is especially useful when dealing with high-dimensional data, group statistics, and panel data.


Creating MultiIndex

Creating from a List

Example

import pandas as pd

# Method 1: Creating using arrays
arrays = [
    ["A", "A", "B", "B", "C", "C"],
    [1, 2, 1, 2, 1, 2]
]

# Using pd.MultiIndex.from_arrays
index = pd.MultiIndex.from_arrays(arrays, names=["Category", "Number"])
print("Created from arrays:")
print(index)
print()

# Method 2: Using a list of tuples
tuples = [
    ("A", 1), ("A", 2), ("B", 1), ("B", 2), ("C", 1), ("C", 2)
]
index = pd.MultiIndex.from_tuples(tuples, names=["Category", "Number"])
print("Created from tuples:")
print(index)
print()

# Method 3: Using product
index = pd.MultiIndex.from_product(
    [["A", "B", "C"], [1, 2, 3]],
    names=["Category", "Number"]
)
print("Created from product:")
print(index)

Creating a DataFrame with MultiIndex

Example

import pandas as pd
import numpy as np

# Creating a DataFrame with MultiIndex
df = pd.DataFrame(
    np.random.randn(6, 4),
    index=pd.MultiIndex.from_tuples(
        [("2024", "Q1"), ("2024", "Q2"), ("2024", "Q3"),
         ("2025", "Q1"), ("2025", "Q2"), ("2025", "Q3")]
    ),
    columns=["Beijing", "Shanghai", "Guangzhou", "Shenzhen"]
)
df.index.names = ["Year", "Quarter"]

print("DataFrame with MultiIndex:")
print(df)

Accessing MultiIndex

Accessing using loc/iloc

Example

import pandas as pd

# Creating sample data
df = pd.DataFrame({
    "Chinese": [85, 92, 78, 88],
    "Math": [90, 88, 95, 82]
}, index=pd.MultiIndex.from_tuples(
    [("Grade 10", "Class A"), ("Grade 10", "Class B"), ("Grade 11", "Class A"), ("Grade 11", "Class B")],
    names=["Grade", "Class"]
))

print("Original data:")
print(df)
print()

# Accessing outer index
print("Accessing all Grade 10:")
print(df.loc["Grade 10"])
print()

# Accessing inner index
print("Accessing Class A:")
print(df.loc[:, "Class A"])
print()

# Accessing multiple index levels
print("Accessing Class A of Grade 10:")
print(df.loc[("Grade 10", "Class A")])

Accessing using xs

Example

import pandas as pd

# Creating sample data
df = pd.DataFrame({
    "Chinese": [85, 92, 78, 88],
    "Math": [90, 88, 95, 82]
}, index=pd.MultiIndex.from_tuples(
    [("Grade 10", "Class A"), ("Grade 10", "Class B"), ("Grade 11", "Class A"), ("Grade 11", "Class B")],
    names=["Grade", "Class"]
))

# Using xs to access values at a specific level
print("Accessing Grade 10 using xs:")
print(df.xs("Grade 10", level="Grade"))
print()

print("Accessing Class A using xs:")
print(df.xs("Class A", level="Class"))

Converting MultiIndex

Stacking and Unstacking

Example

import pandas as pd
import numpy as np

# Creating a wide-format DataFrame
df = pd.DataFrame(
    np.arange(12).reshape(3, 4),
    index=pd.MultiIndex.from_tuples(
        [("Beijing", "2024"), ("Shanghai", "2024"), ("Guangzhou", "2024")]
    ),
    columns=pd.MultiIndex.from_tuples(
        [("Q1", "Revenue"), ("Q1", "Profit"), ("Q2", "Revenue"), ("Q2", "Profit")]
    )
)

print("Original data (nested columns):")
print(df)
print()

# unstack: Convert inner index to columns
df_unstacked = df.unstack()
print("After unstack:")
print(df_unstacked)
print()

# stack: Convert columns to inner index
df_stacked = df_unstacked.stack()
print("After stack:")
print(df_stacked)

Sorting MultiIndex

Example

import pandas as pd

# Creating a DataFrame with unsorted index
df = pd.DataFrame({
    "Value": [1, 2, 3, 4, 5, 6]
}, index=pd.MultiIndex.from_tuples(
    [("C", 2), ("A", 1), ("B", 2), ("A", 2), ("C", 1), ("B", 1)],
    names=["Letter", "Number"]
))

print("Unsorted data:")
print(df)
print()

# Sort by outer level
df_sorted1 = df.sort_index()
print("After sorting by outer level:")
print(df_sorted1)
print()

# Sort by inner level
df_sorted2 = df.sort_index(level=1)
print("After sorting by inner level:")
print(df_sorted2)
print()

# Sort by multiple levels
df_sorted3 = df.sort_index(level=[0, 1])
print("After sorting by multiple levels:")
print(df_sorted3)

Practical: Group Statistics

MultiIndex is very suitable for group statistics and pivot analysis.

Example

import pandas as pd
import numpy as np

# Creating sales data
np.random.seed(42)
df = pd.DataFrame({
    "Year": ["2023"] * 6 + ["2024"] * 6,
    "Quarter": ["Q1", "Q2", "Q3", "Q4"] * 3,
    "Product": ["Phone", "Phone", "Computer", "Computer"] * 3,
    "Region": ["East China", "South China", "North China"] * 4,
    "Sales Amount": np.random.randint(100, 500, 12)
})

print("Original sales data:")
print(df)
print()

# Setting MultiIndex and performing group statistics
df_grouped = df.set_index(["Year", "Quarter", "Product", "Region"])
print("Grouped by year, quarter, product, region:")
print(df_grouped)

# Summarize by year
yearly = df_grouped.groupby(level="Year").sum()
print("\n"Annual sales:")
print(yearly)

# Summarize by year and quarter
quarterly = df_grouped.groupby(level=["Year", "Quarter"]).sum()
print("\n"Quarterly sales:")
print(quarterly)

Common Issues and Notes

1. Index level confusion

Be careful when operating on data to avoid mixing up levels. It is recommended to check before and after operations.df.index.names。

2. Index access errors

locUse label-based access,ilocUse position-based access; do not mix the two.

3. Duplicate index when using concat

When usingconcatto merge data, duplicate indexes may lead to unexpected results. You can useignore_index=Trueto reset.

MultiIndex is a core feature of Pandas for handling high-dimensional data. Using MultiIndex properly can make data organization cleaner and statistics more convenient.

Other Extensions