在 Python 中,groupby 是一个强大的工具,通常用于根据某个键(key)对数据进行分组,当涉及到索引(Index)时,通常指的是使用 pandas DataFrame 或 Series 的索引作为分组键。

以下是几种常见的情况和使用方法:
使用索引值作为分组键
这是最直接的方式,你可以直接将 groupby() 应用于索引,或者将索引重置为一个普通列后再进行分组。
示例:直接对索引分组
假设我们有一个 DataFrame,其索引有重复值,我们想根据这些索引值进行分组。
import pandas as pd
# 创建一个示例 DataFrame
data = {'A': [1, 2, 3, 4, 5, 6],
'B': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar']}
df = pd.DataFrame(data)
# 设置一个有重复值的索引
df.index = ['a', 'b', 'a', 'c', 'b', 'a']
print("原始 DataFrame:")
print(df)
print("\n索引:", df.index.tolist())
# 直接使用索引进行分组
grouped = df.groupby(df.index)
# 遍历分组结果
print("\n分组结果:")
for name, group in grouped:
print(f"\n组名 (索引值): {name}")
print(group)
输出:
原始 DataFrame:
A B
a 1 foo
b 2 bar
a 3 foo
c 4 bar
b 5 foo
a 6 bar
索引: ['a', 'b', 'a', 'c', 'b', 'a']
分组结果:
组名 (索引值): a
A B
a 1 foo
a 3 foo
a 6 bar
组名 (索引值): b
A B
b 2 bar
b 5 foo
组名 (索引值): c
A B
c 4 bar
示例:使用 level 参数(对于多级索引)
如果索引是 MultiIndex(多级索引),你可以使用 level 参数来指定按哪一级或哪几级进行分组。
import pandas as pd
# 创建一个多级索引的 DataFrame
index = pd.MultiIndex.from_tuples([('A', 'X'), ('A', 'Y'), ('B', 'X'), ('B', 'Y')], names=['L1', 'L2'])
data = {'Value': [10, 20, 30, 40]}
df_multi = pd.DataFrame(data, index=index)
print("原始多级索引 DataFrame:")
print(df_multi)
# 按 'L1' 这一级分组
grouped_l1 = df_multi.groupby(level='L1')
print("\n按 'L1' 分组后的结果:")
for name, group in grouped_l1:
print(f"\n组名 (L1): {name}")
print(group)
# 按 'L2' 这一级分组
grouped_l2 = df_multi.groupby(level='L2')
print("\n按 'L2' 分组后的结果:")
for name, group in grouped_l2:
print(f"\n组名 (L2): {name}")
print(group)
输出:
原始多级索引 DataFrame:
Value
L1 L2
A X 10
Y 20
B X 30
Y 40
按 'L1' 分组后的结果:
组名 (L1): A
Value
L2
X 10
Y 20
组名 (L1): B
Value
L2
X 30
Y 40
按 'L2' 分组后的结果:
组名 (L2): X
Value
L1
A 10
B 30
组名 (L2): Y
Value
L1
A 20
B 40
使用索引的一部分作为分组键
你可以从索引中提取一部分信息作为分组键,如果索引是日期,你可能想按年或月进行分组。
示例:按日期的年进行分组
import pandas as pd
# 创建一个带日期索引的 DataFrame
dates = pd.to_datetime(['2025-01-15', '2025-01-20', '2025-02-10', '2025-02-25', '2025-03-05'])
df_date = pd.DataFrame({'Sales': [100, 150, 200, 180, 220]}, index=dates)
print("原始日期索引 DataFrame:")
print(df_date)
# 从索引中提取年份作为分组键
# 方法1: 使用 .dt 访问器
grouped_by_year = df_date.groupby(df_date.index.year)
# 方法2: 使用 lambda 函数
# grouped_by_year = df_date.groupby(lambda x: x.year)
print("\n按年份分组后的销售额总和:")
print(grouped_by_year['Sales'].sum())
输出:
原始日期索引 DataFrame:
Sales
2025-01-15 100
2025-01-20 150
2025-02-10 200
2025-02-25 180
2025-03-05 220
按年份分组后的销售额总和:
2025 850
Name: Sales, dtype: int64
将索引转换为列后进行分组
有时,将索引重置为普通列会更方便,特别是当你需要同时使用索引和列中的值进行分组时。
import pandas as pd
# 使用第一个示例的 DataFrame
data = {'A': [1, 2, 3, 4, 5, 6],
'B': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar']}
df = pd.DataFrame(data)
df.index = ['a', 'b', 'a', 'c', 'b', 'a']
print("原始 DataFrame:")
print(df)
# 将索引重置为列
df_reset = df.reset_index()
print("\n重置索引后的 DataFrame:")
print(df_reset)
# 现在可以像普通列一样使用 'index' 列进行分组
grouped = df_reset.groupby('index')
print("\n使用 'index' 列分组后的结果:")
print(grouped['A'].sum()) # 对每个组的 'A' 列求和
输出:
原始 DataFrame:
A B
a 1 foo
b 2 bar
a 3 foo
c 4 bar
b 5 foo
a 6 bar
重置索引后的 DataFrame:
index A B
0 a 1 foo
1 b 2 bar
2 a 3 foo
3 c 4 bar
4 b 5 foo
5 a 6 bar
使用 'index' 列分组后的结果:
index
a 10
b 7
c 4
Name: A, dtype: int64
| 场景 | 方法 | 示例代码 |
|---|---|---|
| 直接对索引分组 | df.groupby(df.index) |
grouped = df.groupby(df.index) |
| 对多级索引的某一级分组 | df.groupby(level='L1') |
grouped = df_multi.groupby(level='L1') |
| 对索引进行自定义分组 | df.groupby(lambda x: x.year) |
grouped = df_date.groupby(lambda x: x.year) |
| 将索引转为列后分组 | df.reset_index().groupby('index') |
grouped = df.reset_index().groupby('index') |
选择哪种方法取决于你的具体需求和数据结构。groupby 与索引的结合使用非常灵活,是进行数据聚合和分析的核心操作。
