Pandas备忘拾遗 – 多重索引
Jul302020
Pandas 备忘拾遗 – 多重索引
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:80% !important; }</style>"))
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
pd.__version__
'1.0.5'
def df_to_markdown(df):
print(df.to_markdown(tablefmt="github"))
1. 通过数组创建多重索引
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(3, 8), index=['A', 'B', 'C'], columns=index)
df.columns
MultiIndex([('bar', 'one'),
('bar', 'two'),
('baz', 'one'),
('baz', 'two'),
('foo', 'one'),
('foo', 'two'),
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'])
2. 通过数组,长度不一样,进行笛卡尔积创建多重索引
iterables = [['bar', 'baz','qux', 'foo'], ['one', 'two']]
index = pd.MultiIndex.from_product(iterables, names=['first', 'second'])
index
MultiIndex([('bar', 'one'),
('bar', 'two'),
('baz', 'one'),
('baz', 'two'),
('qux', 'one'),
('qux', 'two'),
('foo', 'one'),
('foo', 'two')],
names=['first', 'second'])
3. 多级索引可以看成一级索引,不过每一个索引都是一个元祖
由上面输出可知,多重索引可以看成是一级索引,只不过每一个索引都是一个元祖
,元祖的每一项都对应一个级别的索引
4. 创建一个包含二重索引的DataFrame
df = pd.DataFrame(np.random.randn(3, 8), index=['A', 'B', 'C'], columns=index)
df_to_markdown(df)
(‘bar’, ‘one’) | (‘bar’, ‘two’) | (‘baz’, ‘one’) | (‘baz’, ‘two’) | (‘qux’, ‘one’) | (‘qux’, ‘two’) | (‘foo’, ‘one’) | (‘foo’, ‘two’) | |
---|---|---|---|---|---|---|---|---|
A | -1.33369 | 0.970313 | 0.150361 | -0.917421 | 0.499969 | -1.34554 | -1.24802 | -1.05783 |
B | 0.207102 | 0.100496 | 0.77576 | -0.344869 | 1.02508 | -1.20436 | 0.278921 | 1.72916 |
C | -1.07187 | 0.971974 | -0.590826 | -0.612451 | -0.811501 | -2.13163 | -1.24957 | -1.49083 |
5. 通过levels获取多重索引的level信息
df.columns.levels
FrozenList([['bar', 'baz', 'foo', 'qux'], ['one', 'two']])
6. 多级索引按列获取数据的方法
列为多重索引时,直接使用列名来获取一列时,使用第一级列名,则该列下的所有二级列都或被取到
下面示例df['bar']
可以选出bar
下的二级列one
和two
df_to_markdown(df['bar'])
one | two | |
---|---|---|
A | -1.33369 | 0.970313 |
B | 0.207102 | 0.100496 |
C | -1.07187 | 0.971974 |
7. 使用元祖作为列名,精确定义要获取的那一列数据
df[('bar','two')]
A 0.970313
B 0.100496
C 0.971974
Name: (bar, two), dtype: float64
8. 使用loc方法获取数据
loc方法中括号中接受行,列索引中的level,这个例子中行索引是一级索引A,B,C,而列索引是二级索引,所以loc中表示列的那一项使用元祖,元祖的每一项都可以使用列表选出多个列的.
df_to_markdown(df.loc[['C','B'],(['bar','baz'],['one','two'])])
(‘bar’, ‘one’) | (‘bar’, ‘two’) | (‘baz’, ‘one’) | (‘baz’, ‘two’) | |
---|---|---|---|---|
C | -1.07187 | 0.971974 | -0.590826 | -0.612451 |
B | 0.207102 | 0.100496 | 0.77576 | -0.344869 |
9. 按Index排序DataFrame
sort_index()方法默认按行索引排序,下面代码如果不加.sort_index()输出数据C行在B行前面的,调用sort_index()后,输出时,行是按BC排列的
df_to_markdown(df.loc[['C','B'],(['qux','foo'])])
(‘qux’, ‘one’) | (‘qux’, ‘two’) | (‘foo’, ‘one’) | (‘foo’, ‘two’) | |
---|---|---|---|---|
C | -0.811501 | -2.13163 | -1.24957 | -1.49083 |
B | 1.02508 | -1.20436 | 0.278921 | 1.72916 |
df_to_markdown(df.loc[['C','B'],(['qux','foo'])].sort_index())
(‘qux’, ‘one’) | (‘qux’, ‘two’) | (‘foo’, ‘one’) | (‘foo’, ‘two’) | |
---|---|---|---|---|
B | 1.02508 | -1.20436 | 0.278921 | 1.72916 |
C | -0.811501 | -2.13163 | -1.24957 | -1.49083 |
sort_index()也可以给列排序,传入参数axis=1即可(默认axis=0,给行索引排序),调用sort_index(axis=1)之后,可以看到foo排在qux前面了,按字母排序的.
df_to_markdown(df.loc[['C','B'],(['qux','foo'])].sort_index(axis=1))
(‘foo’, ‘one’) | (‘foo’, ‘two’) | (‘qux’, ‘one’) | (‘qux’, ‘two’) | |
---|---|---|---|---|
C | -1.24957 | -1.49083 | -0.811501 | -2.13163 |
B | 0.278921 | 1.72916 | 1.02508 | -1.20436 |
10. 借助pd.IndexSlice对多重索引进行切片
多重索引进行切片,有时跟单索引体验不太一致,借助pd.IndexSlice可以进行更加符合直觉的切片操作.
下面代码获取所有行,的从(‘bar’,’one’)到(‘foo’,’one’)的数据.注意使用前使用sort_index让DataFrame按行/列索引排序.
注意,二重索引,看成单级索引,每个索引看成一个包含两个元素的元祖.
idx = pd.IndexSlice
df_to_markdown(df.sort_index(axis=0).sort_index(axis=1).loc[idx[:],idx[('bar','one'):('foo','one')]])
(‘bar’, ‘one’) | (‘bar’, ‘two’) | (‘baz’, ‘one’) | (‘baz’, ‘two’) | (‘foo’, ‘one’) | |
---|---|---|---|---|---|
A | -1.33369 | 0.970313 | 0.150361 | -0.917421 | -1.24802 |
B | 0.207102 | 0.100496 | 0.77576 | -0.344869 | 0.278921 |
C | -1.07187 | 0.971974 | -0.590826 | -0.612451 | -1.24957 |
微信赞赏 支付宝赞赏