目录
1. 前言
本文针对pandas初学者,关于pandas使用的文章数不胜数,我刚入门pandas时也是用到时搜索,但是真的很难记住这么多用法,有时感觉很恼火,我认为这是对pandas的一些概念没有系统梳理的结果。因此,本文更多的是根据我个人的理解和使用感受出发,去剖析pandas的某些概念,同时也是对自己学习过程的记录和总结,分享给大家,供大家参考,不喜勿喷。
再强调一下:本文不会照本宣科,本文会尽量去把pandas的基本概念讲清楚,更多的会关注pandas的数据选择问题,即如何对pandas数据进行索引或者是切片。
版本情况:python版本:3.7.6,pandas版本:1.1.2,操作系统:windows 10, IDE:Pycharm 2020.02 社区版
2. pandas简介
Pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);用于数据挖掘和数据分析,同时也提供数据清洗功能。不了解的可以参考此pandas中文网:https://www.pypandas.cn/,有能力的可以去看英文官网。
注意:pandas基于Numpy封装,比Numpy提供了更好的封装和更多的方法。由于基于Numpy,因此在一些属性和方法上与Numpy有类似的用法。
pandas有两大数据结构:
- Series:类似于一维数组的对象,是由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。大家可以把它想象成加强版的list或者是numpy一维数组。这个我用的比较少,就不多说了。
- DataFrame:DataFrame是Pandas中的一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。
DataFrame是pandas的利器,其实就是一个表格结构(类似excel),有很多方法可以用。它有表头(列索引)和行号(行索引)。通过列索引和行索引可以取到表格中的任何数据。在pandas中,列索引叫columns,行索引叫index。本文主要对DataFrame的数据选取问题进行探讨,其他问题后面有时间再写。
3. pandas DataFrame对象结构
观察DataFrame对象结构,可以借助IDE编辑器,我下面列出几个重要的属性或方法,供大家参考。下面是我要使用的测试数据,包括3行5列,表头为:宝贝、价格、成交量、卖家、位置,行号是1,2,3。
行/列索引 | 宝贝 | 价格 | 成交量 | 卖家 | 位置 |
---|---|---|---|---|---|
1 | 新款中老年女装春装雪纺打底衫妈妈装夏装中袖宽松上衣中年人t恤 | 99.0 | 16647 | 夏奈凤凰旗舰店 | 江苏 |
2 | 中老年女装清凉两件套妈妈装夏装大码短袖T恤上衣雪纺衫裙裤套装 | 286.0 | 14045 | 夏洛特的文艺 | 上海 |
3 | 母亲节衣服夏季妈妈装夏装套装短袖中年人40-50岁中老年女装T恤 | 298.0 | 13458 | 云新旗舰店 | 江苏 |
假设DataFrame对象为df,直接打印df,输出为:
print(df) # 输出以下内容
宝贝 价格 成交量 卖家 位置
0 新款中老年女装春装雪纺打底衫妈妈装夏装中袖宽松上衣中年人t恤 99.0 16647 夏奈凤凰旗舰店 江苏
1 中老年女装清凉两件套妈妈装夏装大码短袖T恤上衣雪纺衫裙裤套装 286.0 14045 夏洛特的文艺 上海
2 母亲节衣服夏季妈妈装夏装套装短袖中年人40-50岁中老年女装T恤 298.0 13458 云新旗舰店 江苏
df对象包括的主要属性如下图所示:
我总结了几个重要的属性或方法,并按照我自己的理解给出说明(说错了勿怪):
属性名 | 说明 |
T | 表格转置后的对象(类似矩阵转置) |
columns | 表头,即列索引值 |
index | 行号,即行索引值 |
iloc | iloc方法对象,用于按数字取值,下面会详细说 |
loc | loc方法对象,用于按索引值取值,,下面会详细说 |
shape | 表格大小,此处为[3,5] |
ndim | 表格维数,此处为2维(最常见) |
values | 表格值,是一个numpy的ndarray对象,可见pandas确实基于numpy存储数据 |
价格、位置、宝贝、卖家...... | 每列对应的数据,是一个pandas serise对象 |
dtypes | 一个pandas seires对象,表示每一列的数据类型,常见的有float64,int64,object.... |
通过这些属性,我们可以对dataframe对象的行索引和列索引进行修改,如下:
df.index = ["第一行", "第二行", 4] # 修改行索引值
df.columns = ["商品", "单价", "交易量", "卖家名称", "所在地"] # 修改列索引值
修改效果如下图所示。
还可以通过values属性,将dataframe对象转换成ndarray对象。
data = df.values # data为ndarray对象
其他属性此处不再赘述,大家可自行实验。
4. DataFrame 数据选取
数据选取的意思就是从表格中抽取需要的数据的过程。抽取的数据可能会被组织成pandas series、dataframe对象或者是numpy的ndarray对象,甚至是pyhon内置的list、set、dict对象等,与选取方式有关。
一般来说有四种数据选取需求:
- 行的选取:选取表格中的某行或某几行。
- 列的选取:选取表格中的某列或某几列。
- 块的选取:选取表格中的某几行、某几列
- 根据条件过滤行:按照选取条件,选取某几行。
为什么没有根据条件过滤列?我想原因可能是没必要,因为这样的操作可以通过根据条件过滤行、列的选取两个操作组合实现。
4.1 行的选取
一般,行的选取可以通过如下方式选取,注意返回值依然是Dataframe对象,即使你只取了1行。
df[0:1] # 选取第一行,因为0:1就是[0]
看上去很简单,其实暗藏玄机。通过摸索,我总结下自己的理解:利用该方式取某行或某几行,必须写成 *:* 的形式。
这种方式背后的逻辑就是:取对应位置的行(注意是位置,不是行索引),如0:2,就是取第0行和第1行。如果直接写数字,是取不到的,会报“keyError”错误,如:
df[0] # 本意是想取第0行,实际上会报错 KeyError: 0
这是因为直接写数字,会让pandas认为你是在进行列的选取,从而将0当做键值去读取,列没有0键,自然就会报错。
当然,行的选取肯定还有其他的方法,如利用loc或iloc函数等,这个稍后专门讲。
4.2 列的选取
列的选取,不是根据位置,而是根据键值(或称为标签)来选取,这是与行的选取最重要的区别,请谨记。此种方式返回值为dataframe对象类型。
df[["宝贝"]] # 选取宝贝列
df[["宝贝", "价格"]] # 同时选取多列
针对列的选取, 还可以直接取对应对象的属性值(如前表所示),此种方式返回值为series对象类型。
df.宝贝 # 取"宝贝"对应的列
df.价格 # 取"价格"对应的列
2021年6月修订:
注意:下面的形式返回的同样是series对象,如下所示。
df["宝贝"] # 取"宝贝"对应的列
df["价格"] # 取"价格"对应的列
4.3 块的选取
块的选取,情况比较复杂,无法通过上述的方式取到,需要利用专门的内置函数才能实现。同时,由于行的选取、列的选取都是块的选取的一种特殊情况,因此下面的选取方式同样适用于行的选取和块的选取。
通过搜索就可以看到,目前有很多文章的pandas数据选取介绍,都是围绕块的选取介绍的,只是在逻辑上没有讲清楚,很容易使小白产生困惑感。
块的选取涉及三个函数:loc、iloc和ix。其中,ix函数只有比较老的pandas版本才支持,从0.20.0版本开始,就已经被官方弃用,因此大家可以不用太关心该函数(虽然很多教程中还在讲解)。本文只介绍loc和iloc函数。
4.3.1 loc函数
loc是location的缩写,loc works on labels in the index. 也就是loc for label based indexing。翻译过来就是,loc依赖标签对数据进行定位,标签指的就是我们上面说的表头信息,如宝贝、价格、成交量等
loc函数用法很简单,df.loc[*, *],第一个是行标签,第二个是列标签,如下所示:
df.loc[1,:] # 取第一行,等价于行选取:df[0:1]
df.loc[1,["宝贝","价格"]] # 取第一行,列名为宝贝、价格的列
df.loc[:,"宝贝"] # 取所有行,宝贝列,等价于列选取:df["宝贝"]
这里需要强调的是:本测试数据的行标签为1,2,3,这是人为设置的。如果载入数据时,不指定行标签,则默认从0开始。理论上,行标签不一定要用数字,也可以像列标签一样设置为字符串,如“第一行”、“第二行”、“第三行”,只是用数字表示比较方便,也与人们的使用习惯相符合(比如大家用excel习惯行号是数字)。
4.3.2 iloc函数
iloc可以看做是integer location的缩写,iloc works on the positions in the index (so it only takes integers),也就是:iloc for positional indexing,即iloc依赖于数据的位置,而不是行列标签。行列数据的位置都是从0开始,比如第一行的位置是0,第一列的位置也是0。
iloc函数的用法与loc函数类似,如df.iloc[*, *],第一个是行的位置选择,第二个是列的位置选择。
df.iloc[:,1] # 取所有行,第2列数据
df.iloc[0:2,2:4] # 取第1~2行,第3~4列数据
df.iloc[2,:] # 取第3行数据
4.4 根据条件过滤行
可以在方括号中加入判断条件来过滤行,条件必须返回True或False,判断条件一般根据列名来设置,如
df[(df["价格"]<100) & (df["成交量"]>10000)] # 根据价格和成交量来筛选数据
在根据条件过滤过程中,需要注意以下问题:
- 当进行多个逻辑条件联合过滤时,要使用& 和 |,不要使用and和or。因为,在某些条件下用and/ or会报错‘ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().’;
- 当进行多个逻辑条件联合过滤时,每个逻辑条件需要单独用圆括号包裹,避免出现数据选取达不到预期效果的问题。
4.5 操作返回值说明
行的选取、根据条件过滤行,返回值均是dataframe对象。
列的选取根据选取方式,可能返回dataframe,也可能是series,如前所述。
块的选取返回也取决于具体的操作,其可能是dataframe对象,也可能是series对象,还可能就是一个基本类型数据。返回值的类型会影响对数据的进一步操作,对不同的类型进行相同的操作会出现错误。经过观察,我总结一般规律如下:
- 返回series:选取一行或一列数据,其中选取一行时,与选取的列数无关。
- 返回基本数据类型:选取表格中某一个点。
- 其他情况大都会返回dataframe对象,大家在编程时应予以查看确认,以免出现意外。
5 总结
我相信理解pandas的基本数据结构以及相关对象结构,会加深对pandas不同用法的理解,使自己更加灵活的使用各种用法,而不是现用现查,更不会对众说纷纭的说法和用法产生迷惑。希望本文对大家有所帮助、有所启发,欢迎批评指正。
6 参考文章
- Python pandas 中loc函数的意思及用法,及跟iloc的区别:https://blog.csdn.net/u014712482/article/details/85080864
- pandas 对数据的读取和存储:https://blog.csdn.net/weixin_40041218/article/details/79246883