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 |
array | ExtensionArray |
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 | 时区(别名) |
日期组件属性:
| 属性 | 说明 |
|---|---|
date | datetime.date 对象 |
time | datetime.time 对象 |
year | 年 |
month | 月 |
day | 日 |
hour | 时 |
minute | 分 |
second | 秒 |
microsecond | 微秒 |
nanosecond | 纳秒 |
日历属性:
| 属性 | 说明 |
|---|---|
dayofweek | 星期几(0=周一,6=周日) |
day_of_week | dayofweek 的别名 |
weekday | dayofweek 的别名 |
dayofyear | 一年中的第几天 |
day_of_year | dayofyear 的别名 |
quarter | 季度 |
weekofyear | 一年中的第几周 |
week | weekofyear 的别名 |
days_in_month | 当月天数 |
daysinmonth | days_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_week | dayofweek 的别名 |
dayofyear | 一年中第几天 |
days_in_month | 当月天数 |
daysinmonth | days_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) # 指定层级