Pandas 多層索引
多層索引(MultiIndex)也稱為階層式索引(Hierarchical Index),可以在單一軸上擁有多個層級的索引。這對於處理高維度資料非常有用。
建立多層索引
從 tuple 建立
import pandas as pd
index = pd.MultiIndex.from_tuples([
('A', 1), ('A', 2),
('B', 1), ('B', 2)
])
s = pd.Series([10, 20, 30, 40], index=index)
print(s)
A 1 10
2 20
B 1 30
2 40
dtype: int64
從 arrays 建立
arrays = [
['A', 'A', 'B', 'B'],
[1, 2, 1, 2]
]
index = pd.MultiIndex.from_arrays(arrays, names=['letter', 'number'])
s = pd.Series([10, 20, 30, 40], index=index)
print(s)
從 product 建立
建立所有組合:
index = pd.MultiIndex.from_product(
[['A', 'B'], [1, 2, 3]],
names=['letter', 'number']
)
print(index)
# MultiIndex([('A', 1), ('A', 2), ('A', 3),
# ('B', 1), ('B', 2), ('B', 3)], ...)
使用 set_index
從 DataFrame 欄位建立:
df = pd.DataFrame({
'year': [2023, 2023, 2024, 2024],
'city': ['Taipei', 'Tokyo', 'Taipei', 'Tokyo'],
'sales': [100, 200, 150, 250]
})
df = df.set_index(['year', 'city'])
print(df)
sales
year city
2023 Taipei 100
Tokyo 200
2024 Taipei 150
Tokyo 250
存取多層索引資料
使用 loc
df = pd.DataFrame({
'year': [2023, 2023, 2024, 2024],
'city': ['Taipei', 'Tokyo', 'Taipei', 'Tokyo'],
'sales': [100, 200, 150, 250]
}).set_index(['year', 'city'])
# 選取第一層
print(df.loc[2023])
# 選取特定組合
print(df.loc[(2023, 'Taipei')])
# 選取多個組合
print(df.loc[[(2023, 'Taipei'), (2024, 'Tokyo')]])
使用 xs(cross-section)
# 選取第一層特定值
print(df.xs(2023, level='year'))
# 選取第二層特定值
print(df.xs('Taipei', level='city'))
切片
# 需要先排序索引
df = df.sort_index()
# 切片
print(df.loc[2023:2024])
print(df.loc[(2023, 'Taipei'):(2024, 'Tokyo')])
重設和調整索引
reset_index
# 將所有索引層級轉回欄位
df_flat = df.reset_index()
# 只重設特定層級
df_partial = df.reset_index(level='city')
swaplevel
交換索引層級:
df_swapped = df.swaplevel()
print(df_swapped)
sales
city year
Taipei 2023 100
Tokyo 2023 200
Taipei 2024 150
Tokyo 2024 250
reorder_levels
重新排列索引層級順序:
df_reordered = df.reorder_levels(['city', 'year'])
排序
# 按索引排序
df = df.sort_index()
# 按特定層級排序
df = df.sort_index(level='city')
# 降冪排序
df = df.sort_index(ascending=False)
多層索引的聚合
df = pd.DataFrame({
'year': [2023, 2023, 2023, 2024, 2024, 2024],
'city': ['Taipei', 'Taipei', 'Tokyo', 'Taipei', 'Tokyo', 'Tokyo'],
'sales': [100, 150, 200, 120, 180, 220]
}).set_index(['year', 'city'])
# 按第一層聚合
print(df.groupby(level='year').sum())
# 按第二層聚合
print(df.groupby(level='city').sum())
# 按所有層級聚合
print(df.groupby(level=['year', 'city']).sum())
多層欄位索引
欄位也可以有多層索引:
columns = pd.MultiIndex.from_tuples([
('sales', 'Q1'), ('sales', 'Q2'),
('profit', 'Q1'), ('profit', 'Q2')
])
df = pd.DataFrame([
[100, 120, 10, 12],
[200, 220, 20, 22]
], columns=columns, index=['Taipei', 'Tokyo'])
print(df)
sales profit
Q1 Q2 Q1 Q2
Taipei 100 120 10 12
Tokyo 200 220 20 22
存取:
# 選取第一層
print(df['sales'])
# 選取特定組合
print(df[('sales', 'Q1')])
堆疊和取消堆疊
stack
將欄位轉成索引(寬變長):
df = pd.DataFrame({
'A': [1, 2],
'B': [3, 4]
}, index=['x', 'y'])
stacked = df.stack()
print(stacked)
x A 1
B 3
y A 2
B 4
dtype: int64
unstack
將索引轉成欄位(長變寬):
unstacked = stacked.unstack()
print(unstacked)
A B
x 1 3
y 2 4
指定要 unstack 的層級:
df = pd.DataFrame({
'year': [2023, 2023, 2024, 2024],
'city': ['Taipei', 'Tokyo', 'Taipei', 'Tokyo'],
'sales': [100, 200, 150, 250]
}).set_index(['year', 'city'])
# unstack city
print(df.unstack(level='city'))
sales
city Taipei Tokyo
year
2023 100 200
2024 150 250
實際應用
時間序列的階層資料
# 建立年-月-日的階層索引
df = pd.DataFrame({
'year': [2024] * 6,
'month': [1, 1, 2, 2, 3, 3],
'day': [1, 15, 1, 15, 1, 15],
'value': [100, 110, 120, 115, 130, 125]
}).set_index(['year', 'month', 'day'])
# 取特定月份
print(df.loc[(2024, 2)])
# 按月彙總
print(df.groupby(level='month').sum())