Pandas: Index 索引

最后更新:2026-08-26

Index 是 Pandas 最被低估、却又最强大的特性。它不仅是"行标签"——Index 是数据对齐的核心机制,是 Series 和 DataFrame 运算时自动匹配的"钥匙"。理解了 Index,你就理解了 Pandas 为什么比 NumPy 更适合数据分析。本节深入 Index 的本质、类型和对齐机制。

⚠️ 注意: 以下代码需在本地 Python 环境中运行。

1. 你将学到


2. Alice 的两月销售对齐难题

(1) 痛点:数据行不对齐

Alice 的咖啡店 1 月和 2 月销售天数不同(1 月 31 天,2 月 28 天),而且有些天关门了。她需要把两月数据合并对比:

PYTHON
import pandas as pd

# January sales (some days closed)
jan = pd.Series({'Mon': 320, 'Tue': 280, 'Wed': 350, 'Thu': 410, 'Fri': 390})
# February sales (different days, Mon/Tue closed)
feb = pd.Series({'Wed': 370, 'Thu': 420, 'Fri': 400, 'Sat': 550, 'Sun': 510})

# NumPy-style: would just add position by position — WRONG!
# Pandas: auto-aligns by index label
total = jan + feb
print(total)
# Fri    790.0   ← matched!
# Mon      NaN   ← only in jan
# Sat      NaN   ← only in feb
# Sun      NaN   ← only in feb
# Thu    830.0   ← matched!
# Tue      NaN   ← only in jan
# Wed    720.0   ← matched!
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(2) 解法:Index 自动对齐

Pandas 运算时按 Index 标签自动对齐——相同标签的值相加,不同标签填 NaN。你不需要手动匹配数据。

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:对齐运算与 fill_value(难度⭐⭐)

PYTHON
import pandas as pd

jan = pd.Series({'Mon': 320, 'Tue': 280, 'Wed': 350, 'Thu': 410, 'Fri': 390})
feb = pd.Series({'Wed': 370, 'Thu': 420, 'Fri': 400, 'Sat': 550, 'Sun': 510})

# Fill missing with 0 for cleaner comparison
total = jan.add(feb, fill_value=0)
print(total.sort_index())
# Fri    790.0
# Mon    320.0   ← jan only, feb=0
# Sat    550.0   ← feb only, jan=0
# Sun    510.0   ← feb only, jan=0
# Thu    830.0
# Tue    280.0   ← jan only, feb=0
# Wed    720.0
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(3) 收益:Index 对齐避免隐蔽 bug

如果用 NumPy 按位置相加,jan[0] + feb[0] 就是 320 + 370 = 690——但 Mon 和 Wed 根本不是同一天!Index 对齐让你从"位置匹配"的错误中解放出来。


3. Index 的本质与类型

(1) Index 不是普通数组

Index 是一个不可变的、类似 ndarray 的对象,专门用于标签索引和对齐。它的关键特性:

100%
graph TB
    IDX["Index (Base)"] --> RI["RangeIndex<br/>auto-generated 0,1,2,..."]
    IDX --> DI["DatetimeIndex<br/>time-based labels"]
    IDX --> CI["CategoricalIndex<br/>finite set of categories"]
    IDX --> MI["MultiIndex<br/>hierarchical labels"]
    IDX --> GI["General Index<br/>arbitrary labels"]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(2) Index 类型对比

类型 创建方式 典型场景 特殊功能
RangeIndex 默认 未指定 index 时 内存高效
Index 手动指定 字符串/数字标签 通用
DatetimeIndex pd.date_range 时间序列 频率/偏移/重采样
CategoricalIndex dtype='category' 有限类别 有序/无序分类
MultiIndex from_tuples/from_product 层次数据 分层选取

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:Index 类型检查(难度⭐)

PYTHON
import pandas as pd

# RangeIndex (default)
s1 = pd.Series([1, 2, 3])
print(type(s1.index))   # <class 'pandas.core.indexes.range.RangeIndex'>

# General Index (string labels)
s2 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
print(type(s2.index))   # <class 'pandas.core.indexes.base.Index'>

# DatetimeIndex
dates = pd.date_range('2026-01-01', periods=5)
s3 = pd.Series([100, 200, 150, 300, 250], index=dates)
print(type(s3.index))   # <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

4. set_index 与 reset_index

(1) set_index:把列变为行标签

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:set_index 用法(难度⭐)

PYTHON
import pandas as pd

df = pd.DataFrame({
    'product': ['Coffee', 'Tea', 'Juice'],
    'price': [4.50, 3.80, 5.20],
    'category': ['Hot', 'Hot', 'Cold']
})

# Set product as index
df_indexed = df.set_index('product')
print(df_indexed)
#          price category
# product
# Coffee   4.50      Hot
# Tea      3.80      Hot
# Juice    5.20     Cold

print(df_indexed.loc['Coffee', 'price'])  # 4.5

# Drop the column after setting (default=True)
# Keep the column: drop=False
df_keep = df.set_index('product', drop=False)
print(df_keep.columns)  # still has 'product'
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(2) reset_index:把行标签还原为列

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:reset_index 用法(难度⭐)

PYTHON
import pandas as pd

df = pd.DataFrame({
    'price': [4.50, 3.80, 5.20]
}, index=['Coffee', 'Tea', 'Juice'])

# Reset index back to column
df_reset = df.reset_index()
print(df_reset)
#    index  price
# 0  Coffee   4.50
# 1     Tea   3.80
# 2    Juice   5.20

# Name the new column
df_reset2 = df.reset_index(names='product')
print(df_reset2.columns)  # Index(['product', 'price'])

# Drop index entirely (don't keep as column)
df_drop = df.reset_index(drop=True)
print(df_drop)
#    price
# 0   4.50
# 1   3.80
# 2   5.20
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(3) set_index vs reset_index 对比

操作 set_index reset_index
方向 列→行标签 行标签→列
原列 默认删除(drop=True) 保留为新列
默认 index 无(需指定列) RangeIndex(0,1,2,...)
就地修改 默认否(inplace=False) 默认否

5. 索引对齐机制详解

(1) 对齐规则

当两个 Pandas 对象(Series 或 DataFrame)做运算时:

  1. 取两者 Index 的并集
  2. 匹配的标签做运算
  3. 不匹配的标签填 NaN
100%
graph LR
    A["Series A<br/>{a:1, b:2, c:3}"] --> ADD["A + B"]
    B["Series B<br/>{b:20, c:30, d:40}"] --> ADD
    ADD --> R["Result<br/>{a:NaN, b:22, c:33, d:NaN}"]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:DataFrame 对齐(难度⭐⭐)

PYTHON
import pandas as pd

df1 = pd.DataFrame({'A': [1, 2, 3]}, index=['x', 'y', 'z'])
df2 = pd.DataFrame({'A': [10, 20, 30]}, index=['y', 'z', 'w'])

result = df1 + df2
print(result)
#       A
# w   NaN
# x   NaN
# y  22.0
# z  33.0

# With fill_value
result2 = df1.add(df2, fill_value=0)
print(result2)
#       A
# w  30.0
# x   1.0
# y  22.0
# z  33.0
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。
💡 提示: Index 对齐不仅发生在 +、-、*、/ 运算中,也发生在 add/sub/mul/div 等方法中。fill_value 参数只对缺失的一方生效,双方都缺失时结果仍为 NaN。


6. reindex 与 align

(1) reindex:重塑索引

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:reindex 用法(难度⭐⭐)

PYTHON
import pandas as pd

s = pd.Series([320, 280, 350], index=['Mon', 'Tue', 'Wed'])

# Reindex to include new labels (fill with NaN)
s_full = s.reindex(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])
print(s_full)
# Mon    320.0
# Tue    280.0
# Wed    350.0
# Thu      NaN
# Fri      NaN

# Fill missing values
s_filled = s.reindex(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'], fill_value=0)
print(s_filled)

# Forward fill (use previous value)
s_ffill = s.reindex(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'], method='ffill')
print(s_ffill)
# Thu gets Wed's value (350)
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(2) align:对齐两个 Series

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:align 对齐(难度⭐⭐)

PYTHON
import pandas as pd

s1 = pd.Series({'a': 1, 'b': 2, 'c': 3})
s2 = pd.Series({'b': 20, 'c': 30, 'd': 40})

# Align both to union index
s1_aligned, s2_aligned = s1.align(s2)
print(s1_aligned)
# a    1.0
# b    2.0
# c    3.0
# d    NaN

print(s2_aligned)
# a     NaN
# b    20.0
# c    30.0
# d    40.0

# Align with fill_value
s1_f, s2_f = s1.align(s2, fill_value=0)
print(s1_f)
# a    1
# b    2
# c    3
# d    0
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

(3) reindex vs align 对比

方法 作用 适用场景
reindex 按新索引重塑单个对象 扩展/重排索引
align 同时对齐两个对象 两个对象互相匹配

7. Index 常用属性与方法

(1) 属性速查

属性/方法 说明 示例结果
idx.is_unique 是否唯一 True / False
idx.is_monotonic_increasing 是否单调递增 True / False
idx.has_duplicates 是否有重复 True / False
idx.nunique() 唯一值个数 7
idx.duplicated() 重复标记 布尔数组
idx.drop_duplicates() 去重 新 Index

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:Index 属性检查(难度⭐)

PYTHON
import pandas as pd

idx1 = pd.Index(['a', 'b', 'c', 'd'])
idx2 = pd.Index(['a', 'b', 'b', 'c'])

print(idx1.is_unique)       # True
print(idx2.is_unique)       # False
print(idx2.has_duplicates)  # True
print(idx1.nunique())       # 4
print(idx2.duplicated())    # [False, False, True, False]
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

8. 完整示例:月度销售数据对齐与重组

▶ 示例

TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

:两月销售对齐全流程(难度⭐⭐⭐)

PYTHON
import pandas as pd
import numpy as np

# ============================================
# Comprehensive example: Monthly sales data
# alignment and reorganization using Index
# ============================================

# 1. Two months of daily sales (different days)
jan = pd.Series({
    '2026-01-06': 320, '2026-01-07': 280, '2026-01-08': 350,
    '2026-01-09': 410, '2026-01-10': 390
}, name='jan_sales')
feb = pd.Series({
    '2026-02-04': 370, '2026-02-05': 420, '2026-02-06': 400,
    '2026-02-07': 550
}, name='feb_sales')

# 2. Index info
print("=== Index Analysis ===")
print(f"Jan unique: {jan.index.is_unique}")    # True
print(f"Feb unique: {feb.index.is_unique}")    # True

# 3. Align both months to common format
jan_a, feb_a = jan.align(feb, fill_value=0)
print(f"\n=== Aligned Data ===")
comparison = pd.DataFrame({'jan': jan_a, 'feb': feb_a})
print(comparison)

# 4. Set index on DataFrame for label-based access
df = pd.DataFrame({
    'product': ['Latte', 'Cappuccino', 'Espresso', 'Mocha', 'Americano'],
    'price': [5.50, 4.80, 3.50, 5.20, 3.00],
    'category': ['Specialty', 'Specialty', 'Classic', 'Specialty', 'Classic']
})
print(f"\n=== Products by Category ===")
df_cat = df.set_index('category')
print(df_cat.loc['Specialty', ['product', 'price']])

# 5. Reindex to ensure all weekdays present
weekday_sales = pd.Series(
    [320, 280, 350, 410, 390],
    index=['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
)
full_week = weekday_sales.reindex(
    ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    fill_value=0
)
print(f"\n=== Full Week Sales ===")
print(full_week)
TEXT 📖 仅展示
> **输出:** 在本地 Python 环境(pandas 2.x)运行。Piston 服务器未预装 pandas,请在本机安装(`pip install pandas`)后实操对照。实际数值会因 pandas 版本略有差异。

❓ 常见问题

Q Index 可以重复吗?
A 可以。Pandas 允许重复 Index,但访问重复标签时返回多个值(一个 Series 而非标量),且会降低性能。用 s.index.is_unique 检查唯一性。建议尽量保持 Index 唯一。
Q set_index 会丢失数据吗?
A 默认 drop=True 会把列从 DataFrame 中移除变为 Index。如果需要保留列,用 df.set_index('col', drop=False)。Index 信息始终可以通过 reset_index 还原为列。
Q 对齐机制什么时候触发?
A 所有二元运算(+、-、*、/、add、sub 等)自动触发 Index 对齐。比较运算(>、<、==)也会对齐。赋值操作(s1[s1 > 0] = ...)不触发对齐。DataFrame 之间的运算同时按行 Index 和列 Columns 对齐。
Q reindex 和 loc 区别?
A reindex 可以添加新标签(用 fill_value 填充),loc 只能访问已有标签(访问不存在的标签报 KeyError)。reindex 的目的是"重塑索引到指定格式",loc 的目的是"按标签选取数据"。
Q 什么时候用 CategoricalIndex?
A 当标签是有限的类别集合时(如星期、月份、州名),CategoricalIndex 能节省内存并保证标签范围。例如用 CategoricalIndex 确保 reindex 时星期一到星期日都出现。
Q Index 不可变怎么修改?
A Index 对象本身不可变,但可以用 df.index = new_index 整体替换,或用 df.rename(index=...) 重命名标签。不能对 Index 的单个元素赋值。
Q reset_index 的 drop 参数有什么用?
A drop=True 时丢弃原 Index(不保留为列),得到干净的 RangeIndex。drop=False(默认)时把原 Index 还原为普通列。常见场景:groupby 后 reset_index(drop=True) 清除分组键。

📖 小节


📝 作业

  1. 基础题(难度⭐):创建一个 Series(5 个城市人口),用 set_index 和 reset_index 在 DataFrame 上做转换,观察 index 变化。
  2. 进阶题(难度⭐⭐):创建两个 Index 不完全相同的 Series,分别用 + 运算和 add(fill_value=0) 做加法,对比结果差异。然后用 align 方法对齐两个 Series。
  3. 挑战题(难度⭐⭐⭐):用 DatetimeIndex 创建两月销售数据(1 月和 2 月,日期不同),用 reindex 补全两月所有日期(缺失填 0),计算两月同日对比的增长率。

← 上一课:DataFrame 核心 · 下一课:数据类型 →

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏