索引的创建,取值,排序
1.多层索引的创建
多层索引是Pandas中一个比较核心的概念,允许你在一个轴向上拥有多个索引层级,许多同学不能处理复杂的数据,最大的问题在于没法灵活的处理多层索引。
import pandas as pd s = pd.Series([1, 2, 3, 4, 5, 6], index=[['张三', '张三', '李四', '李四', '王五', '王五'], ['期中', '期末', '期中', '期末', '期中', '期末']]) print(s)
✨效果
张三 期中 1 期末 2 李四 期中 3 期末 4 王五 期中 5 期末 6 dtype: int64
从图中数据可以看出,张三那一列是数据的第一层索引,期中那一列是数据的第二层索引,而第二层索引值是和数据一一对应的。
但是,我们在创建的时候发现,也需要将名字和考试阶段一一对应,才可以。
🚩现在,我们将数据增加几个科目的成绩,演示DataFrame多层索引的创建方法。
由于成绩的数据比较多,我们将使用numpy的随机数方法构建成绩数据。
numpy会在后续中讲解,现在大家先体验一下,如何使用numpy构建实验数据
import pandas as pd import numpy as np #size参数是指定生成6行3列的数组 data = np.random.randint(0,100,size=(6,3)) names = ['张三','李四','王五'] exam = ['期中','期末'] index = pd.MultiIndex.from_product([names,exam]) df = pd.DataFrame(data,index=index,columns=['Java','Web','Python']) df
✨下面是运行的效果,我用表格形式来为大家展示
Java | Web | Python | ||
张三 | 期中 | 84 | 35 | 57 |
期末 | 96 | 36 | 92 |
李四 | 期中 | 42 | 5 | 64 |
期末 | 47 | 55 | 76 | |
王五 | 期中 | 81 | 34 | 74 |
期末 | 54 | 81 | 69 |
我们虽然成功的创建了DataFrame的多层索引,但是有一个问题,在设置索引的时候会有很多重复的索引值,如何才能简化索引的写法呢?
Pandas为了解决这个问题,提供了一个创建多层索引的构造方法。
pd.MultiIndex.from_product()构建索引的方式
首先,确定每一层索引的值什么,然后以列表的形势传给from_product()方法即可。
import pandas as pd import numpy as np data = np.random.randint(0,100,size=(6,3)) names = ['张三','李四','王五'] exam = ['期中','期末'] index = pd.MultiIndex.from_product([names,exam]) df = pd.DataFrame(data,index=index,columns=['Java','Web','Python']) print(df)
✨效果
我们成功创建了DataFrame的多层索引,而且你会发现,我们只需要关注每层索引的值都有哪些就可以了。
[names,exam]列表中的位置不同,产生的索引也会不同。
import pandas as pd import numpy as np data = np.random.randint(0,100,size=(6,3)) names = ['张三','李四','王五'] exam = ['期中','期末'] index = pd.MultiIndex.from_product([exam,names]) df = pd.DataFrame(data,index=index,columns=['Java','Web','Python']) print(df)
✨效果
🚩经过上面的两段代码,下面我们一起总结一下:
第一:from_product([exam,names])会将列表中第一个元素作为最外层索引,依次类推;
第二:列表中元素值的对应关系,如下图:
2.多层索引的取值
创建不是我们的目的,我们的目的是如何从多层索引中获取到我们想要的数据。
看下面的代码
import pandas as pd s = pd.Series([1,2,3,4,5,6],index=[['张三','张三','李四','李四','王五','王五'], ['期中','期末','期中','期末','期中','期末']]) print(s)
可以直接使用[]的方式取最外面的一个层级s[‘张三’]
🚩注意:[]取值方式,不可直接使用最外层以外的其他层级,例如:s[‘期末’],并且[‘张三’,‘期末’]他们的顺序不能变。
不知道大家是否还记得loc和iloc的使用?
loc使用的是标签索引,iloc使用的是位置索引。
loc的使用方式和[]的方式基本一样:
但是,iloc的取值并不会受多层索引影响,只会根据数据的位置索引进行取值。
import pandas as pd import numpy as np #size参数是指定生成6行3列的数组 data = np.random.randint(0,100,size=(6,3)) names = ['张三','李四','王五'] exam = ['期中','期末'] index = pd.MultiIndex.from_product([names,exam]) df = pd.DataFrame(data,index=index,columns=['Java','Web','Python']) df.iloc[0]
✨效果
Java 84 Web 35 Python 57 Name: (张三, 期中), dtype: int32
在对多层索引DataFrame的取值是,我们推荐使用loc()函数。
同时对一二级索引进行检索:
df.loc['张三'].loc['期中']
✨效果
Java 84 Web 35 Python 57 Name: 期中, dtype: int32
df.loc[('张三','期中')]
✨效果
Java 84 Web 35 Python 57 Name: (张三, 期中) dtype: int32
🚩注意:DataFrame中对行索引的时候和Series有一个同样的注意点,就是无法直接对二级索引直接进行索引,必须让二级索引变成一级索引后才能对其进行索引!
3.多层索引的排序
有时候,我们需要将分组或创建出来的多层索引数据,根据索引值进行排序。
我们先创建一个简单的多层索引数据:
import pandas as pd data = np.random.randint(0, 100, size=(9, 3)) key1 = ['b', 'c', 'a'] key2 = [2, 1, 3] index = pd.MultiIndex.from_product([key1, key2]) df = pd.DataFrame(data, index=index, columns=['Java', 'Web', 'Python']) df
✨效果
Java | Web | Python | ||
a | 2 | 19 | 70 | 14 |
1 | 27 | 6 | 14 | |
3 | 93 | 27 | 46 |
b | 2 | 35 | 88 | 87 |
1 | 23 | 31 | 99 | |
3 | 59 | 90 | 17 | |
c | 2 | 73 | 40 | 58 |
1 | 14 | 86 | 87 | |
3 | 10 | 5 | 75 |
DataFrame按行索引排序的方法是sort_index(),接下来我们看一下sort_index()是如何对多层索引进行排序。
默认状态下的排序
df.sort_index()
✨效果
通过结果可以看出每一层都会根据索引值进行相应的升序排列。
df.sort_index()中的level参数可以指定是否按照指定的层级进行排列,第一层级索引值为0,第二层级索引值为1。
当level=0时,会根据第一层索引值进行降序排序:df.sort_index(level=0, ascending=False)
✨效果
通过上面的几个排序发现,可以通过level设置排序的索引层级,其他层索引也会根据其排序规则进行排序。
当level=1时,会根据第二层索引值进行降序排序:
✨效果
Java | Web | Python | ||
c | 3 | 10 | 5 | 75 |
b | 3 | 59 | 90 | 17 |
a | 3 | 93 | 27 | 46 |
c | 2 | 14 | 86 | 87 |
b | 2 | 23 | 31 | 99 |
a | 2 | 27 | 6 | 14 |
c | 1 | 73 | 40 | 58 |
b | 1 | 35 | 88 | 87 |
a | 1 | 19 | 70 | 14 |
通过结果可以看出数据会根据第二层索引值进行相应的降序排列,如果索引值相同时会根据其他层索引值排列