主要包含 pandas 中的分层索引概念,以及特定的数据操作
1. 分层索引
1.1 分层索引简单介绍
- 分层索引允许在一个轴上拥有多个索引层级,即提供一种在更低维度的形式上处理更高维度的数据的方式,一个简单的例子:
import pandas as pd
import numpy as np
data = pd.Series(np.random.randn(9),
index=[['a', 'a', 'a' ,'b', 'b', 'c', 'c', 'd', 'd'],
[1, 2, 3, 1, 3, 1, 2, 2, 3]])
# 列表的列表(或数组)作为索引
data:以 MultiIndex 作为索引的 Series
a 1 0.624702
2 0.614184
3 -0.908469
b 1 -1.516634
3 -0.822532
c 1 0.382908
2 -1.413468
d 2 1.632027
3 0.972743
dtype: float64
data.index:
MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]],
codes=[[0, 0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 2, 0, 1, 1, 2]])
- 通过分层索引对象选择出数据的子集
data_b = data['b']
data_b2c = data['b':'c']
data_bd = data.loc[['b', 'd']]
data_inside = data.loc[:, 2] # 在“内部”层级进行选择
- stack(堆叠)与 unstack(拆分)
unstack = data.unstack() # 将数据在 DataFrame 中重新排列
stack = unstack.stack() # 将 DataFrame 堆叠为分层索引 Series,unstack 的反操作
unstack:
1 | 2 | 3 | |
---|---|---|---|
a | 0.624702 | 0.614184 | -0.908469 |
b | -1.516634 | NaN | -0.822532 |
c | 0.382908 | -1.413468 | NaN |
d | NaN | 1.632027 | 0.972743 |
- DataFrame 中,每个轴都可以拥有分层索引
frame = pd.DataFrame(np.arange(12).reshape((4, 3)),
index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
columns=[['Ohio', 'Ohio', 'Colorado'],['Green', 'Red', 'Green']])
frame:
Ohio | Colorado | |||
---|---|---|---|---|
Green | Red | Green | ||
a | 1 | 0 | 1 | 2 |
2 | 3 | 4 | 5 | |
b | 1 | 6 | 7 | 8 |
2 | 9 | 10 | 11 |
- 分层的层级可以有名称,如果层级有名称,则名称会在控制台输出中显示:
frame.index.names = ['key1', 'key2']
frame.columns.names = ['State', 'Color']
ohio = frame.['Ohio'] # 通过部分列索引选出列中的组
frame:
State | Ohio | Colorado | ||
---|---|---|---|---|
Color | Green | Red | Green | |
key1 | key2 | |||
a | 1 | 0 | 1 | 2 |
2 | 3 | 4 | 5 | |
b | 1 | 6 | 7 | 8 |
2 | 9 | 10 | 11 |
ohio:
Color | Green | Red | |
---|---|---|---|
key1 | key2 | ||
a | 1 | 0 | 1 |
2 | 3 | 4 | |
b | 1 | 6 | 7 |
2 | 9 | 10 |
- 一个 MultiIndex 对象可以使用其自身的构造函数创建并复用:
columns = pd.MultiIndex.from_arrays([['Ohio', 'Ohio', 'Colrado'], ['Green', 'Red', 'Green']],
names=['states', 'color'])
1.2 重排序和层级排序——swaplevel & sort_index
- 使用 swaplevel 方法对层级进行变更,但数据不变,该方法返回一个新的对象;
- 使用 sort_index 进行层级排序;
frame_2 = frame.swaplevel('key1', 'key2') # 交换 key1 和 key2
frame_3 = frame.sort_index(level=1) # 按照key2 进行排序
frame_4 = frame.swaplevel(0, 1).sort_index(level=0) # 交换第1层和第2层,然后按交换后的第1层排序
frame_2:
State | Ohio | Colorado | ||
---|---|---|---|---|
Color | Green | Red | Green | |
key2 | key1 | |||
1 | a | 0 | 1 | 2 |
2 | a | 3 | 4 | 5 |
1 | b | 6 | 7 | 8 |
2 | b | 9 | 10 | 11 |
frame_3:
State | Ohio | Colorado | ||
---|---|---|---|---|
Color | Green | Red | Green | |
key1 | key2 | |||
a | 1 | 0 | 1 | 2 |
b | 1 | 6 | 7 | 8 |
a | 2 | 3 | 4 | 5 |
b | 2 | 9 | 10 | 11 |
frame_4:
State | Ohio | Colorado | ||
---|---|---|---|---|
Color | Green | Red | Green | |
key2 | key1 | |||
1 | a | 0 | 1 | 2 |
b | 6 | 7 | 8 | |
2 | a | 3 | 4 | 5 |
b | 9 | 10 | 11 |
1.3 按层级进行汇总统计
DataFrame 和 Series 大部分描述性和汇总统计都包含 level 选项,以指定在某个特定的轴上进行聚合:
sum_key2 = frame.sum(level='key2') # 在 key2 上进行求和
sum_coloer = frame.sum(level='color', axis=1) # 在列索引 color 上进行求和
sum_key2:
State | Ohio | Colorado | |
---|---|---|---|
Color | Green | Red | Green |
key2 | |||
1 | 6 | 8 | 10 |
2 | 12 | 14 | 16 |
sum_color:
Color | Green | Red | |
---|---|---|---|
key1 | key2 | ||
a | 1 | 2 | 1 |
2 | 8 | 4 | |
b | 1 | 14 | 7 |
2 | 20 | 10 |
1.4 使用 DataFrame 的列进行索引——set_index
- 使用 set_index 可以将 DataFrame 中的一个或多个列作为行索引(返回一个新的对象),默认情况下这些列会从 DataFame 中移除,使用 drop 选项将其留下
- reset_index 是 set_index 的反操作:
frame = pd.DataFrame({
'a': range(7),
'b': range(7, 0, -1),
'c':['one', 'one', 'one', 'two', 'two', 'two', 'two'],
'd': [0, 1, 2, 0, 1, 2, 3]})
frame2 = frame.set_index(['c', 'd']) # 将 c 和 d 列设为行索引
frame3 = frame.set_index(['c', 'd'], drop=False) # 将 c 和 d 列设为行索引并保留这两列
frame4 = frame2.reset_index() # 将分层索引移动到列中
frame:
a | b | c | d | |
---|---|---|---|---|
0 | 0 | 7 | one | 0 |
1 | 1 | 6 | one | 1 |
2 | 2 | 5 | one | 2 |
3 | 3 | 4 | two | 0 |
4 | 4 | 3 | two | 1 |
5 | 5 | 2 | two | 2 |
6 | 6 | 1 | two | 3 |
frame2:
a | b | ||
---|---|---|---|
c | d | ||
one |