Index 是 pandas 的标签机制核心。它不仅仅是”行号”,还提供了高效的查找、对齐、去重、集合运算能力,并派生多种专用索引类型。


3.1 创建

构造方法:pd.Index()

idx = pd.Index([1, 2, 3])
idx_str = pd.Index(['a', 'b', 'c'], name='字母')

构造参数:

参数说明
data数据源:列表、ndarray、RangeIndex 等
dtype数据类型(如 int64、datetime64[ns])
name索引名称
copy是否复制输入数据
tupleize_cols是否将元组列转换为 MultiIndex(默认 True)

3.2 属性

属性说明
name索引名称
names索引名称(MultiIndex 使用)
dtype数据类型
dtypes与 dtype 一致
shape形状
size大小
ndim维度
nbytes内存字节数
empty是否为空
is_unique是否无重复
has_duplicates是否有重复
is_monotonic_increasing是否单调递增
is_monotonic_decreasing是否单调递减
values底层 ndarray
arrayExtensionArray
T转置(一维下通常返回自身)

3.3 方法

查询

方法说明
get_loc(label)获取标签的整数位置
get_indexer(labels)获取多个标签的整数位置
get_indexer_non_unique(labels)处理非唯一标签的位置索引
slice_indexer(start, end)获取切片的整数索引
slice_locs(start, end)切片位置边界(不含端点)

排序

方法说明
sort_values()按值排序
sort()已弃用,用 sort_values 替代
argsort()返回排序后位置索引
searchsorted(value)查询值应插入的位置

唯一

方法说明
unique()返回唯一值 Index
nunique()唯一值个数
value_counts()频次统计
duplicated()标记重复
drop_duplicates()删除重复

集合

方法说明
intersection(other)交集
union(other)并集
difference(other)差集
symmetric_difference(other)对称差集

操作

方法说明
append(other)追加另一个 Index
drop(labels)删除指定标签
insert(loc, value)在指定位置插入值
join(other)连接操作(交集/并集等)
map(func)元素映射
rename(name)重命名
set_names(names)设置名称(MultiIndex)
dropna()删除缺失标签
fillna(value)填充缺失标签
repeat(repeats)重复元素
take(indices)按位置取值
delete(loc)删除指定位置的元素
copy()复制
astype(dtype)类型转换
to_list()转为 Python 列表
to_numpy()转为 NumPy 数组
to_flat_index()MultiIndex 转为扁平 Index
str字符串访问器
where(cond)条件替换
isin(values)判断是否属于指定集合

3.4 索引类型

RangeIndex

高效的整数范围索引,类似 range() 对象。

属性说明
start起始值
stop终止值(不包含)
step步长
# 等价于 range(0, 10, 2)
idx = pd.RangeIndex(0, 10, 2)

CategoricalIndex

基于分类数据的索引,底层为 Categorical 对象。适用于类别型数据的有序索引与快速分组选择。

idx = pd.CategoricalIndex(['a', 'b', 'a'], categories=['a', 'b', 'c'])

MultiIndex

多层索引,用于处理高维数据(内存中模拟三维及以上)。

属性:

属性说明
levels各层级的唯一值列表
codes各元素在各层级的整数编码
names各层级名称
nlevels索引层数
levshape各层级大小元组

静态构造方法:

方法说明
from_arrays(arrays)从多个数组创建
from_tuples(tuples)从元组列表创建
from_product(iterables)从多个可迭代对象的笛卡尔积创建
from_frame(frame)从 DataFrame 的列创建

实例方法:

方法说明
set_levels(levels)设置层级标签
set_codes(codes)设置编码
get_level_values(level)获取指定层级的标签
droplevel(level)删除指定层级
swaplevel(i, j)交换两个层级
reorder_levels(order)重新排列层级顺序
remove_unused_levels()删除未使用的类别
sortlevel(level)按指定层级排序
# 从元组创建
idx = pd.MultiIndex.from_tuples([('A', 1), ('A', 2), ('B', 3)], names=['组', '序号'])
 
# 从乘积创建(笛卡尔积)
idx = pd.MultiIndex.from_product([['A', 'B'], [1, 2]])

DatetimeIndex

时间索引,是时间序列分析的核心。支持频率、时区、日历属性、边界判断等。

频率与时区属性:

属性说明
freq频率对象(如 D、M、H)
freqstr频率字符串
inferred_freq自动推断的频率
tz时区
timezone时区(别名)

日期组件属性:

属性说明
datedatetime.date 对象
timedatetime.time 对象
year年
month月
day日
hour时
minute分
second秒
microsecond微秒
nanosecond纳秒

日历属性:

属性说明
dayofweek星期几(0=周一,6=周日)
day_of_weekdayofweek 的别名
weekdaydayofweek 的别名
dayofyear一年中的第几天
day_of_yeardayofyear 的别名
quarter季度
weekofyear一年中的第几周
weekweekofyear 的别名
days_in_month当月天数
daysinmonthdays_in_month 的别名

边界判断属性:

属性说明
is_month_start是否为月初
is_month_end是否为月末
is_quarter_start是否为季初
is_quarter_end是否为季末
is_year_start是否为年初
is_year_end是否为年末
is_leap_year是否为闰年

常用方法:

方法说明
month_name()月份名称(如 January)
day_name()星期名称(如 Monday)
to_period()转为 Period 索引
to_pydatetime()转为 Python datetime 数组
tz_localize(tz)本地化时区(无时区 → 有时区)
tz_convert(tz)转换时区(有时区 → 另一时区)
normalize()归一到午夜
round(freq)时间取整
floor(freq)时间向下取整
ceil(freq)时间向上取整
strftime()格式化时间字符串
snap()对齐到最近频率
as_unit(unit)调整时间单位
idx = pd.date_range('2024-01-01', periods=3, freq='D')
print(idx.year)          # [2024 2024 2024]
print(idx.month)         # [1 1 1]
print(idx.dayofweek)     # [0 1 2](周一、周二、周三)
print(idx.day_name())    # ['Monday', 'Tuesday', 'Wednesday']

TimedeltaIndex

时间差索引,表示持续时间或时间间隔。

属性/方法说明
days天数
seconds秒数
microseconds微秒
nanoseconds纳秒
components各时间分量(天、时、分、秒等)
total_seconds()总秒数
to_pytimedelta()转为 Python timedelta 数组
round()时间取整
floor()时间向下取整
ceil()时间向上取整
idx = pd.timedelta_range('1 day', periods=3, freq='D')
print(idx.days)               # [1 2 3]
print(idx.total_seconds())    # [86400 172800 259200]

PeriodIndex

周期索引,表示固定频率的时间段(如月度、季度),适合周期性数据分析。

属性/方法说明
freq频率
start_time周期开始时间
end_time周期结束时间
year年
month月
quarter季度
day日
hour时
minute分
second秒
week第几周
dayofweek星期几
day_of_weekdayofweek 的别名
dayofyear一年中第几天
days_in_month当月天数
daysinmonthdays_in_month 的别名
to_timestamp()转为时间戳索引
tz_localize(tz)时区本地化
tz_convert(tz)时区转换
idx = pd.period_range('2024-01', periods=3, freq='M')
print(idx.year)          # [2024 2024 2024]
print(idx.month)         # [1 2 3]
print(idx.start_time)    # ['2024-01-01' '2024-02-01' '2024-03-01']

IntervalIndex

区间索引,每个元素是一个区间 [left, right]。

属性/方法说明
left区间左端点
right区间右端点
mid区间中点
length区间长度
closed边界类型:left、right、both、neither
is_non_overlapping_monotonic区间是否无重叠且单调
contains(value)区间是否包含指定值
get_loc(value)值所在区间的整数位置
overlaps(other)是否与另一区间重叠
idx = pd.interval_range(start=0, end=5, freq=1)
print(idx.left)    # [0 1 2 3 4]
print(idx.right)   # [1 2 3 4 5]
print(idx.length)  # [1 1 1 1 1]

3.5 MultiIndex 高级操作

创建多层索引

import pandas as pd
 
# 方式一:from_arrays
arrays = [[1, 1, 2, 2], ['红', '蓝', '红', '蓝']]
idx = pd.MultiIndex.from_arrays(arrays, names=['编号', '颜色'])
 
# 方式二:from_tuples
tuples = [(1, '红'), (1, '蓝'), (2, '红'), (2, '蓝')]
idx = pd.MultiIndex.from_tuples(tuples, names=['编号', '颜色'])
 
# 方式三:from_product(笛卡尔积)
idx = pd.MultiIndex.from_product([['A', 'B'], [1, 2]], names=['组', '序号'])
 
# 方式四:from_frame
df = pd.DataFrame({'a': [1, 2], 'b': ['x', 'y']})
idx = pd.MultiIndex.from_frame(df)

使用 level 参数

在 groupby、sort_index、stack、unstack 等方法中,通过 level 参数指定操作的层级:

df = pd.DataFrame({'值': [1, 2, 3, 4]}, index=idx)
 
# 按第一层分组求和
df.groupby(level='编号').sum()
 
# 按第二层排序
df.sort_index(level='颜色')
 
# 将第一层索引转为列
df.stack(level=0)

切片和部分选择

# 选择第一层级的全部数据
df.loc['A']
 
# 选择多层级精确组合
df.loc[('A', 1)]

IndexSlice

使用 pd.IndexSlice 对 MultiIndex 进行优雅切片:

import pandas as pd
 
idx = pd.MultiIndex.from_product([['A', 'B'], [2023, 2024, 2025]])
df = pd.DataFrame({'值': range(6)}, index=idx)
 
# 选择 'A' 层级,年份在 2023 到 2024 之间
df.loc[pd.IndexSlice['A', 2023:2024], :]
 
# 选择 'A' 的全部 + 'B' 的 2023
df.loc[pd.IndexSlice[['A', 'B'], 2023], :]

cross-section xs()

按指定层级获取交叉切片,返回减少一个层级的 DataFrame/Series:

# 获取 'A' 的所有行(剥离第一层索引)
df.xs('A')
 
# 指定多层级组合
df.xs(('A', 2023))
 
# 按列进行 xs
df.xs('值', axis=1)

stack / unstack

多层索引与列之间的相互转换:

# 将最内层索引转为列(数据变长)
df.stack()
 
# 将列转为索引(数据变宽)
df.unstack()
df.unstack(level=0)  # 指定层级