一、为什么要学习分层索引 Multindex?
- 分层索引:在个轴向上拥有多个素引1层级,可以表达更高维度数据的形式;
- 可以更方便的进行数据筛选,如果有序则性能更好
- groupby等操作的结果,如果是多KEY,结果是分层索引,需要会使用
- 一般不需要自己创建分层索引(Multilndex有构造函数, 但一般不用)
二、基本用法
演示数据:百度、阿里巴巴、爱奇艺、京东四家公司的10天股票数据
数据来自:英为财经
本次演示提纲:
- Series的分层索引Multilndex
- Series有多层索引怎样筛选数据?
- DataFrame的多层索引Multilndex?
- DataFrame有多层素引怎样筛选数据?
fpath = '/Users/python/Desktop/means/ml-25m/互联网公司股票.xlsx'
df = pd.read_excel(fpath)日期 公司 收盘 开盘 高 低 交易量 涨跌幅
0 2019-10-03 BIDU 104.32 102.35 104.73 101.15 2.24 0.02
1 2019-10-02 BIDU 102.62 100.85 103.24 99.50 2.69 0.01
2 2019-10-01 BIDU 102.00 102.80 103.26 101.00 1.78 -0.01
3 2019-10-03 BABA 169.48 166.65 170.18 165.00 10.39 0.02
4 2019-10-02 BABA 165.77 162.82 166.88 161.90 11.60 0.00
df.shape 查看数据的总的行列
(12, 8)
df.head(3) 查看数据的前3行日期 公司 收盘 开盘 高 低 交易量 涨跌幅
0 2019-10-03 BIDU 104.32 102.35 104.73 101.15 2.24 0.02
1 2019-10-02 BIDU 102.62 100.85 103.24 99.50 2.69 0.01
2 2019-10-01 BIDU 102.00 102.80 103.26 101.00 1.78 -0.01
df['公司'].unique() 查看包含哪些公司
array(['BIDU', 'BABA', 'IQ', 'JD'], dtype=object)
df.index 查看索引的索引列
RangeIndex(start=0, stop=12, step=1)
以公司进行分组,查看公司收盘价的平均值
df.groupby('公司')['收盘'].mean()公司
BABA 166.80
BIDU 102.98
IQ 15.90
JD 28.35
Name: 收盘, dtype: float64
三、Series 的分层索引Multilndex
以公司和日期进行分组,取收盘价的平均值
ser = df.groupby(['公司', '日期'])['收盘'].mean()公司 日期 (公司是一个索引,日期也是一个索引)
BABA 2019-10-01 165.152019-10-02 165.772019-10-03 169.48
BIDU 2019-10-01 102.002019-10-02 102.622019-10-03 104.32
IQ 2019-10-01 15.922019-10-02 15.722019-10-03 16.06
JD 2019-10-01 28.192019-10-02 28.062019-10-03 28.80
Name: 收盘, dtype: float64
ser.index 查看ser.index索引
MultiIndex([('BABA', '2019-10-01'),('BABA', '2019-10-02'),('BABA', '2019-10-03'),('BIDU', '2019-10-01'),('BIDU', '2019-10-02'),('BIDU', '2019-10-03'),( 'IQ', '2019-10-01'),( 'IQ', '2019-10-02'),( 'IQ', '2019-10-03'),( 'JD', '2019-10-01'),( 'JD', '2019-10-02'),( 'JD', '2019-10-03')],names=['公司', '日期'])
ser.unstack()日期 2019-10-01 2019-10-02 2019-10-03
公司
BABA 165.15 165.77 169.48
BIDU 102.00 102.62 104.32
IQ 15.92 15.72 16.06
JD 28.19 28.06 28.80
两层索引都变成了普通的列,原来的Series 变成dataframe
ser.reset_index()公司 日期 收盘
0 BABA 2019-10-01 165.15
1 BABA 2019-10-02 165.77
2 BABA 2019-10-03 169.48
3 BIDU 2019-10-01 102.00
4 BIDU 2019-10-02 102.62
5 BIDU 2019-10-03 104.32
6 IQ 2019-10-01 15.92
7 IQ 2019-10-02 15.72
8 IQ 2019-10-03 16.06
9 JD 2019-10-01 28.19
10 JD 2019-10-02 28.06
11 JD 2019-10-03 28.80
三、Series 有多层索引Multilndex如何筛选数据
ser公司 日期
BABA 2019-10-01 165.152019-10-02 165.772019-10-03 169.48
BIDU 2019-10-01 102.002019-10-02 102.622019-10-03 104.32
IQ 2019-10-01 15.922019-10-02 15.722019-10-03 16.06
JD 2019-10-01 28.192019-10-02 28.062019-10-03 28.80
Name: 收盘, dtype: float64
筛选一级索引
ser.loc['BIDU'] 筛选百度的数据日期
2019-10-01 102.00
2019-10-02 102.62
2019-10-03 104.32
Name: 收盘, dtype: float64
多层索引,可以用元组的形式筛选
如果筛选第一级索引,第二级索引
ser.loc[('BIDU', '2019-10-02')]102.62
如果直接筛选第二级的索引
ser.loc[:, '2019-10-02']公司
BABA 165.77
BIDU 102.62
IQ 15.72
JD 28.06
Name: 收盘, dtype: float64
四、DataFrame的多层索引MultiIndex
df.head()日期 公司 收盘 开盘 高 低 交易量 涨跌幅
0 2019-10-03 BIDU 104.32 102.35 104.73 101.15 2.24 0.02
1 2019-10-02 BIDU 102.62 100.85 103.24 99.50 2.69 0.01
2 2019-10-01 BIDU 102.00 102.80 103.26 101.00 1.78 -0.01
3 2019-10-03 BABA 169.48 166.65 170.18 165.00 10.39 0.02
4 2019-10-02 BABA 165.77 162.82 166.88 161.90 11.60 0.00
DataFrame 如何设置分层索引
将公司名和日期设置为分层索引
df.set_index(["公司", "日期"], inplace=True)收盘 开盘 高 低 交易量 涨跌幅
公司 日期
BIDU 2019-10-03 104.32 102.35 104.73 101.15 2.24 0.022019-10-02 102.62 100.85 103.24 99.50 2.69 0.012019-10-01 102.00 102.80 103.26 101.00 1.78 -0.01
BABA 2019-10-03 169.48 166.65 170.18 165.00 10.39 0.022019-10-02 165.77 162.82 166.88 161.90 11.60 0.002019-10-01 165.15 168.01 168.23 163.64 14.19 -0.01
IQ 2019-10-03 16.06 15.71 16.38 15.32 10.08 0.022019-10-02 15.72 15.85 15.87 15.12 8.10 -0.012019-10-01 15.92 16.14 16.22 15.50 11.65 -0.01
JD 2019-10-03 28.80 28.11 28.97 27.82 8.77 0.032019-10-02 28.06 28.00 28.22 27.53 9.53 0.002019-10-01 28.19 28.22 28.57 27.97 10.64 0.00
df.index # 查看df.index索引
MultiIndex([('BIDU', '2019-10-03'),('BIDU', '2019-10-02'),('BIDU', '2019-10-01'),('BABA', '2019-10-03'),('BABA', '2019-10-02'),('BABA', '2019-10-01'),( 'IQ', '2019-10-03'),( 'IQ', '2019-10-02'),( 'IQ', '2019-10-01'),( 'JD', '2019-10-03'),( 'JD', '2019-10-02'),( 'JD', '2019-10-01')],names=['公司', '日期'])
df.sort_index(inplace=True) 对分组后结果重新排序,会按照字母、number类型自动排序;通过一级、二级进行排序收盘 开盘 高 低 交易量 涨跌幅
公司 日期
BABA 2019-10-01 165.15 168.01 168.23 163.64 14.19 -0.012019-10-02 165.77 162.82 166.88 161.90 11.60 0.002019-10-03 169.48 166.65 170.18 165.00 10.39 0.02
BIDU 2019-10-01 102.00 102.80 103.26 101.00 1.78 -0.012019-10-02 102.62 100.85 103.24 99.50 2.69 0.012019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
IQ 2019-10-01 15.92 16.14 16.22 15.50 11.65 -0.012019-10-02 15.72 15.85 15.87 15.12 8.10 -0.012019-10-03 16.06 15.71 16.38 15.32 10.08 0.02
JD 2019-10-01 28.19 28.22 28.57 27.97 10.64 0.002019-10-02 28.06 28.00 28.22 27.53 9.53 0.002019-10-03 28.80 28.11 28.97 27.82 8.77 0.03
五、DataFrame有多层索引MultiIndex如何筛选数据
在选择数据时:
元组(key1, key2)代表第选多层索引,其中key1是索引第一级,key2是第二级,比如key1=JD, key2=2019-10-02
列表[key1, key2]代表同一层的多个KEY.其中key1和key2是并列的同级索引,比如key1=JD, key2=BIDU
筛选第一层索引
df.loc['BIDU'] 查询百度相关的数据 收盘 开盘 高 低 交易量 涨跌幅
日期
2019-10-01 102.00 102.80 103.26 101.00 1.78 -0.01
2019-10-02 102.62 100.85 103.24 99.50 2.69 0.01
2019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
筛选多层索引 传入元组
df.loc[('BIDU', '2019-10-02'), :] 查询一级索引是BIDU,二级索引是2019-10-02 数据 (取所有列)收盘 102.62
开盘 100.85
高 103.24
低 99.50
交易量 2.69
涨跌幅 0.01
Name: (BIDU, 2019-10-02), dtype: float64
多层索引下查询某个单元格
df.loc[('BIDU', '2019-10-02'), '收盘'] # 查询一级索引是BIDU,二级索引是2019-10-02 收盘的价格(取单个单元格)
102.62
并列筛选:如果是列表,同一级索引
df.loc[['BIDU', 'JD'], :] 查询BIDU,JD的所有日期的数据 收盘 开盘 高 低 交易量 涨跌幅
公司 日期
BIDU 2019-10-01 102.00 102.80 103.26 101.00 1.78 -0.012019-10-02 102.62 100.85 103.24 99.50 2.69 0.012019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
JD 2019-10-01 28.19 28.22 28.57 27.97 10.64 0.002019-10-02 28.06 28.00 28.22 27.53 9.53 0.002019-10-03 28.80 28.11 28.97 27.82 8.77 0.03
混合筛选
df.loc[(['BIDU', 'JD'], '2019-10-02'), :] 查询BIDU、JD在2019-10-02所有数据收盘 开盘 高 低 交易量 涨跌幅
公司 日期
BIDU 2019-10-02 102.62 100.85 103.24 99.50 2.69 0.01
JD 2019-10-02 28.06 28.00 28.22 27.53 9.53 0.00
df.loc[(['BIDU', 'JD'], '2019-10-02'), '收盘'] 查询BIDU、JD在2019-10-02的收盘价是多少公司 日期
BIDU 2019-10-02 102.62
JD 2019-10-02 28.06
Name: 收盘, dtype: float64
df.loc[('BIDU', ['2019-10-02', '2019-10-03']), '收盘'] 查询BIDU在2019-10-02、2019-10-03两天的收盘价公司 日期
BIDU 2019-10-02 102.622019-10-03 104.32
Name: 收盘, dtype: float64
slice(None) 代表筛选这以索引的所有内容
df.loc[(slice(None), ['2019-10-02', '2019-10-03']), :] 查询所有公司在2019-10-02、2019-10-03两天的数据 (slice(None) 只能这样写)收盘 开盘 高 低 交易量 涨跌幅
公司 日期
BABA 2019-10-02 165.77 162.82 166.88 161.90 11.60 0.002019-10-03 169.48 166.65 170.18 165.00 10.39 0.02
BIDU 2019-10-02 102.62 100.85 103.24 99.50 2.69 0.012019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
IQ 2019-10-02 15.72 15.85 15.87 15.12 8.10 -0.012019-10-03 16.06 15.71 16.38 15.32 10.08 0.02
JD 2019-10-02 28.06 28.00 28.22 27.53 9.53 0.002019-10-03 28.80 28.11 28.97 27.82 8.77 0.03
df.reset_index() 把多级索引变成普通的列公司 日期 收盘 开盘 高 低 交易量 涨跌幅
0 BABA 2019-10-01 165.15 168.01 168.23 163.64 14.19 -0.01
1 BABA 2019-10-02 165.77 162.82 166.88 161.90 11.60 0.00
2 BABA 2019-10-03 169.48 166.65 170.18 165.00 10.39 0.02
3 BIDU 2019-10-01 102.00 102.80 103.26 101.00 1.78 -0.01
4 BIDU 2019-10-02 102.62 100.85 103.24 99.50 2.69 0.01
5 BIDU 2019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
6 IQ 2019-10-01 15.92 16.14 16.22 15.50 11.65 -0.01
7 IQ 2019-10-02 15.72 15.85 15.87 15.12 8.10 -0.01
8 IQ 2019-10-03 16.06 15.71 16.38 15.32 10.08 0.02
9 JD 2019-10-01 28.19 28.22 28.57 27.97 10.64 0.00
10 JD 2019-10-02 28.06 28.00 28.22 27.53 9.53 0.00
11 JD 2019-10-03 28.80 28.11 28.97 27.82 8.77 0.03