首先我们要明确索引的作用。在SQL中我们通过索引能够快速的定位数据,就像一本书的目录一样,通过目录我们可以快速的定位到书中的某个章节。在pandas里面,我们通过索引进行数据的选取和筛选。就像在一张大表里面选取我们需要分析或者感兴趣的内容,此时就需要用到索引的相关操作。这个是pandas中基本操作,需要熟练掌握。因为一维的Series比较简单,我们以二维的数据结构DataFrame为例进行总结。主要包括以下内容:
- 列选取,选取一列或者多列
- 行选取
- loc和iloc选取(主要内容,经常用)
- Query方法选取
下面通过代码实战进行演练。下面代码中涉及的数据集和代码可以在后台回复“pandas”获取
import numpy as np
import pandas as pd
df = pd.read_csv('learn_pandas.csv')
df.head()
![](https://img.haomeiwen.com/i21406194/2d73f3692f72e944.png)
这是一个包含学生姓名/性别和学校以及身高体重等信息的表格
1.列选取:根据要求选择一列或者多列
对于DataFrame的列,可以使用“[]”操作符或者"."进行选择,使用“.”时要注意,列明不能有空格如下:
# 通过列标签选择数据
df['School'].head()
>>>
0 Shanghai Jiao Tong University
1 Peking University
2 Shanghai Jiao Tong University
3 Fudan University
4 Fudan University
Name: School, dtype: object
要同时选取多列时,一般是先创建一个列表,将所需要的内容放入列表中,再将该列表整体传入df中:
use_col = ['Name', 'Gender', 'Height', 'Test_Date']
df[use_col].head(5)
结果如下:
![](https://img.haomeiwen.com/i21406194/16ae20f52cd37d14.png)
2. 行选取
当要求按照某个字段的条件筛选某些行时,可以直接将该条件作为一个condition传入df中,举例:
- 筛选 Peking University的学生:
# 直接按照条件带入带入:
df[df['School'] == 'Peking University'].head()
# 上面的写法等价于:
condition = (df['School'] == 'Peking University')
df[condition].head
>>>
结果如下:
![](https://img.haomeiwen.com/i21406194/332b70e952c667dc.png)
- 筛选身高大于165的同学:
df[df['Height'] > 165].head()
![](https://img.haomeiwen.com/i21406194/ec7af64a770d7b80.png)
3. loc和iloc
在实际实战中,按照一定条件选择数据更常用的方法是loc和iloc, 两者的语法结构类似,不同之处在于:
- loc : 基于label索引器,列名和行号都可以作为label
- iloc: 基于index索引的索引器
这两个容易混淆,实际中可以按照首字母记忆,即loc和label都是“l”开头,iloc和index都是“i”开头。
语法结构以loc为例,iloc一样:
df. loc[*, *] ,其中第一个 * 代表行的选择,第二个 * 代表列的选择,如果省略第二个位置写作 loc[] ,这个 * 是指行的筛选。
其中, * 的位置一共有五类合法对象,分别是:单个元素、元素列表、元素切片、布尔列表以及函数,常用的为前面4个,下面将依次说明。
我们以loc为例,前面说了,loc是基于label选取的,我们把行索引index设置为Name,这样更容易说明。
df_new = df.set_index('Name')
df_new.head()
![](https://img.haomeiwen.com/i21406194/6d9105a524d38369.png)
【a】 * 为单个元素
此时,直接取出相应的行或列,如果该元素在索引中重复则结果为 DataFrame,否则为 Series
df_new.loc['Gaojuan You'] # 原表格中只有一行满足条件,返回一个Series
>>>
School Fudan University
Grade Sophomore
Gender Male
Height 174.0
Weight 74.0
Transfer N
Test_Number 2
Test_Date 2019/11/6
Time_Record 0:05:22
Name: Gaojuan You, dtype: object
df_new.loc['Qiang Sun'] # 原表格中有多行满足条件,返回一个DataFrame
![](https://img.haomeiwen.com/i21406194/9e5c21de18cd6264.png)
【b】 * 为元素列表
此时,取出列表中所有元素值对应的行或列:
df_new.loc[['Qiang Sun', 'Xiaojuan Sun'],['School', 'Gender', 'Weight']]
![](https://img.haomeiwen.com/i21406194/5b1fd2803184b1b9.png)
【c】 * 为切片
之前的 Series 使用字符串索引时提到,如果是唯一值的起点和终点字符,那么就可以使用切片,并且包含两个端点,如果不唯一则报错:
df_new.loc['Changqiang You':'Gaoqiang Qian', 'School':'Test_Number']
![](https://img.haomeiwen.com/i21406194/bf9e568ac76ab2ed.png)
【d】 * 为布尔列表
在前面的行选取中,其实我们已经使用了和loc布尔列表类似的操作了。我们在来看一下上面例子中的表达式: df[df['Height'] > 165],在该表达式中:
- 第一步:内部的“df['Height'] > 165” 返回一个与 DataFrame 长度相同的布尔列表
- 第二步:外面在套上df后,实际上执行了一个筛选操作,即且列表为 True 的位置所对应的行会被选中, False 则会被剔除。
df.loc也可以完成相同的功能:
(df.loc[df['School'] == 'Tsinghua University' ]) == (df[df['School'] == 'Tsinghua University'])
![](https://img.haomeiwen.com/i21406194/82d6efbddef5bda0.png)
在实际操作中,往往需要根据多个条件来选取数据,对于这种复合条件而言,可以用 |(或), &(且), ~(取反) 的组合来实现。
实战操作: 选取复旦大学中体重超过70kg的大四学生,或者北大男生中体重超过80kg的非大四的学生:
condition_1_a = df_new['School'] == 'Fudan University'
condition_1_b = df_new['Grade'] == 'Senior'
condition_1_c = df_new['Weight'] > 70
condition_1 = condition_1_a & condition_1_b & condition_1_c
condition_2_a = df_new.School == 'Peking University'
condition_2_b = df_new.Grade == 'Senior'
condition_2_c = df_new.Weight > 80
condition_2 = condition_2_a & (~condition_2_b) & condition_2_c
res = df_new.loc[condition_1 | condition_2]
res
结果如下:
![](https://img.haomeiwen.com/i21406194/0173f8b0782c5f2b.png)
iloc 的使用与 loc 完全类似,只不过是针对index索引进行筛选,因为行/列的索引index均是从0开始的整数,因而在相应的 * 位置处一共也有五类合法对象,分别是:整数、整数列表、整数切片、布尔列表以及函数,函数的返回值必须是前面的四类合法对象中的一个,其输入同样也为 DataFrame 本身。
这个方法有一个常用的场景,就是在机器学习的数据集划分中。例如在一个大表中,前面的列为特征,最后一列为对应的标签,这时需要将除去最后一列的数据作为X,最后一列的值作为标签Y,例如在上面的表格中,我们可以:
X = df.iloc[:, :-1] # : 前面为行,不写表示选取所有行,后面为列,-1为最后一列,不包括
Y = df['Time_Record']
4. Query方法
在 pandas 中,支持把字符串形式的查询表达式传入 query 方法来查询数据,其表达式的执行结果必须返回布尔列表。在进行复杂索引时,由于这种检索方式无需像普通方法一样重复使用 DataFrame 的名字来引用列名,一般而言会使代码长度在不降低可读性的前提下有所减少。
例如,可以将上面loc方法的复合选取改用query方法来做:
# 将 loc 一节中的复合条件查询例子可以如下改写:
df.query('((School == "Fudan University")&'
' (Grade == "Senior")&'
' (Weight > 70))|'
'((School == "Peking University")&'
' (Grade != "Senior")&'
' (Weight > 80))')
![](https://img.haomeiwen.com/i21406194/f14d1d7390f27d80.png)
在 query 表达式中,系统自动帮用户注册了所有来自 DataFrame 的列名,所有属于该 Series 的方法都可以被调用,和正常的函数调用并没有区别,即在调用是无需在声明df['列名‘]的形式,直接使用列名。例如查询体重超过均值且性别为女的学生:
df.query('(Weight > Weight.mean())' and '(Gender == "Female")').head(6)
部分结果如下:
![](https://img.haomeiwen.com/i21406194/49e0549e59a1a0c8.png)
参考:开源内容Joyful Pandas, 作者 DataWhale耿远昊
另外,更多精彩内容也可以微信搜索,并关注公众号:‘Python数据科学家之路“ ,期待您的到来和我交流
网友评论