自学教程 学编程从这里开始

Pandas Index 详解

Index 是 Pandas 的核心底层组件,Series 自带索引,DataFrame 拥有行索引 index、列索引 columns。索引不只是序号,它负责对齐、分组、切片、性能加速、多表合并。本文讲解基础索引、常用索引类型、构造、修改、切片、对齐、多级索引、索引优化、踩坑,延续整套教程风格。
前置导入

import pandas as pd
import numpy as np

一、索引是什么

  • Series:values + index
  • DataFrame:行索引 df.index,列索引 df.columns
  • Index 是不可变序列,哈希化,支持快速查找;不能直接修改单个元素
  • 核心作用:数据自动对齐、标签筛选、分组、join、排序、高性能定位
s = pd.Series([10,20,30], index=["a","b","c"])
print(s.index)
df = pd.DataFrame({"x":[1,2],"y":[3,4]}, index=["p1","p2"])
print(df.index)
print(df.columns)

Index 常见子类:

  1. RangeIndex:默认整数索引(0,1,2…),省内存
  2. Index:通用标签索引(字符串、数字)
  3. DatetimeIndex:时间索引(时序分析、股票行情高频)
  4. MultiIndex:多级索引(分组、透视表)
  5. CategoricalIndex:分类索引
  6. PeriodIndex:周期索引(年月季度)
  7. Float64Index / Int64Index:数值索引

二、创建 Index

2.1 基础构造

# 普通索引
idx = pd.Index(["apple","banana","orange"], name="fruit")
# 整数索引
idx_int = pd.Index([101,102,103])
# 时间索引
dt_idx = pd.date_range("2026-01-01", periods=5, freq="D")
# 多级索引
midx = pd.MultiIndex.from_tuples([("线上","键盘"),("线上","鼠标")], names=["渠道","商品"])

2.2 从已有数据生成索引

df = pd.DataFrame({
    "商品":["键盘","鼠标","显示器"],
    "金额":[178,45,1200]
})
# 设置行索引
df = df.set_index("商品")
print(df.index)

三、索引基本属性与方法

idx = pd.Index(["a","b","c","d"])
# 属性
idx.name       # 索引名称
idx.values     # 底层numpy数组
idx.is_unique  # 是否唯一(非常重要!)
idx.is_monotonic_increasing # 是否单调递增(切片、搜索加速)
idx.has_duplicates # 是否存在重复值

# 常用方法
idx.append(pd.Index(["e"]))
idx.drop("a")
idx.unique()
idx.sort_values()
idx.get_indexer(["b","d"]) # 返回位置下标
idx.isin(["b","c"])        # 成员判断,返回布尔数组

⚠️ Index 不可变:idx[0] = "x" 直接报错,修改必须生成新索引。

四、RangeIndex(默认索引)

新建DataFrame不指定index时,默认就是 RangeIndex

df = pd.DataFrame({"a":[1,2,3]})
print(type(df.index)) # RangeIndex

特点:

  • 不存储全部数字,只存 start, stop, step,内存极小
  • 一旦手动赋值、reset_index,经常变成普通 Int64Index

五、DatetimeIndex 时间索引(时序重点)

dates = pd.date_range("2026-01-01", periods=10, freq="D")
s = pd.Series(range(10), index=dates)
# 强大的切片语法
s["2026-01-03"]
s["2026-01-01":"2026-01-05"]
s["2026-01"] # 取整个1月
# 按时间偏移、重采样
s.resample("3D").sum()

时间索引支持:year, month, day, weekday, hour 访问器。

六、索引定位:loc / iloc 核心区分

  • loc:按索引标签查找(匹配 index 的值)
  • iloc:按位置下标查找(0,1,2…)
df = pd.DataFrame({"val":[10,20,30]}, index=["x","y","z"])
df.loc["y"]
df.iloc[1]

坑:当索引是数字时,很容易混淆 loc 和 iloc!
比如 index=[2,4,6],df.loc[2] 是匹配标签2,不是第2行。

七、索引修改 set_index / reset_index

df = pd.DataFrame({
    "商品":["键盘","鼠标"],
    "渠道":["线上","线下"],
    "金额":[178,45]
})
# 设置索引
df1 = df.set_index("商品")
# 多列设为多级索引
df2 = df.set_index(["渠道","商品"])
# 索引变回普通列
df3 = df1.reset_index()
# 重置索引并丢弃旧索引
df4 = df1.reset_index(drop=True)

八、索引对齐(Pandas最独特的机制)

两个Series/DataFrame运算时,自动按索引对齐,匹配不上的位置填充NaN

s1 = pd.Series([1,2,3], index=["a","b","c"])
s2 = pd.Series([10,20], index=["b","c"])
s = s1 + s2
print(s)

输出:a:NaN,b:12,c:23
很多新手疑惑为什么相加后出现NaN,根源就是索引对不齐。

align 手动对齐两个索引:

s1_align, s2_align = s1.align(s2, fill_value=0)

九、MultiIndex 多级索引

df = pd.DataFrame({
    "数量":[2,1,3,2],
    "金额":[178,45,267,90]
}, index=pd.MultiIndex.from_tuples(
    [("线上","键盘"),("线上","鼠标"),("线下","键盘"),("线下","鼠标")],
    names=["渠道","商品"]
))
# 取一级索引
df.loc["线上"]
# 两层精确取值
df.loc[("线上","键盘")]
# 交换层级
df.swaplevel("渠道","商品")
# 排序索引(多级索引强烈建议排序,提升loc性能)
df = df.sort_index()

多级索引如果不排序,切片 df.loc["线上":] 会报错。

展平多级索引:

df = df.reset_index()

十、索引排序 sort_index

df = df.sort_index()
# 列索引排序
df = df.sort_index(axis=1)
# 降序
df = df.sort_index(ascending=False)

索引排序后:

  • loc切片支持范围选取
  • 查找、join、merge 速度大幅提升

十一、索引去重、唯一索引

很多高级操作(join、asof、快速loc查询)要求索引唯一:

# 检查重复
df.index.has_duplicates
# 去重,保留第一个
df = df[~df.index.duplicated(keep="first")]

duplicated 参数:keep="first"/"last"/False

十二、reindex 重建索引(补行、补时间缺口)

reindex 按照新索引序列重新排列数据,缺失位置填充NaN或指定值

s = pd.Series([10,20], index=["a","b"])
new_idx = ["a","b","c","d"]
s_new = s.reindex(new_idx, fill_value=0)

时序场景补全交易日、自然日缺口高频使用:

idx_all = pd.date_range("2026-01-01","2026-01-10", freq="D")
df = df.reindex(idx_all)

十三、索引性能优化(配合前面性能优化章节)

  1. 高频查询、关联字段设为索引,loc O(1),远快于布尔筛选
  2. 索引尽量保证唯一、单调递增
  3. 优先 DatetimeIndex 做时序,不要用字符串日期
  4. 分组键如果固定,设置为索引,groupby更快
  5. join 比 merge 快的前提:两边关联键都是索引
df1.join(df2) # 索引对索引连接,速度更快
  1. 避免频繁 reset_index / set_index,会产生副本、消耗内存

十四、列索引 columns 操作

columns 本质也是 Index 对象

df.columns.name = "指标"
# 重命名列
df = df.rename(columns={"金额":"销售金额"})
# 列索引转列表
col_list = df.columns.tolist()

十五、常见坑汇总

  1. 索引是数字标签时,loc 和 iloc 极易混淆
  2. 多级索引未排序,范围切片报错
  3. 运算出现莫名NaN:索引没有对齐
  4. 重复索引:loc 会返回多行,很多算法、join不支持重复索引
  5. DatetimeIndex 带时区和不带时区的时间索引不能对齐
  6. 不要在循环里频繁 set_index / reset_index,产生大量副本
  7. RangeIndex 一旦修改,会变成普通Int64Index,内存变大

十六、Index 速查表

操作作用
df.index / df.columns读取行、列索引
set_index设置列为行索引
reset_index索引变回普通列
sort_index索引排序
reindex按新索引重排、补缺失
loc标签索引取值
iloc位置下标取值
MultiIndex多层索引
is_unique / has_duplicates检查重复索引
align两个对象索引对齐

十七、实战模板:时序标准索引流程

def set_time_index(df):
    df["date"] = pd.to_datetime(df["date"])
    df = df.set_index("date")
    df = df.sort_index()
    # 补全日历日期,空缺填充0
    idx_range = pd.date_range(start=df.index.min(), end=df.index.max(), freq="D")
    df = df.reindex(idx_range, fill_value=0)
    return df
标签:

0 条笔记