选取数据
Pandas 的数据结构和你管理 Excel 很像,特别是 DataFrame 就约等于 Excel 当中的 sheet。 我们非常适应用 Excel 来选择和修改数据,但是如果把它程序化,用代码来修改和选取的时候,我们该如何操作呢?
Pandas 的数据选取,和 List,Numpy Array 还是有挺大差别的,因为它想要维护了很多的人类可读的索引信息, 所以它在索引的时候,也有不一样的处理方式,今天我们就来看看 Pandas 是如何处理数据选取和修改的吧。
这次需要使用到的一些功能:
多种选取方式¶
在 Pandas 中,有丰富的选取数据方式,这可比 List,Dictionary,甚至是 Numpy 还要多样化。我们既能通过文字标签来定位数据,也能通过数值序号来定位。 所以为了实现这种多样性,Pandas 对于数据的选取采用了不同类型的处理方法,比如 .loc
, .iloc
等,我们下面一一来介绍一下吧。
面对应用比较多的工作学习场景,我先以 Excel 型的表格数据举例,请你帮我构建一下下面这份 DataFrame:
选Column¶
看到了上面这份数据后,我们发现,DataFrame 会分 Column 和 Row(index)。如果你搞机器学习,通常我们的 Column 是特征,Row 是数据样本, 在要对某个特征进行分析的时候,比如要做特征数值分布的分析,我们得把特征取出来吧。 那么你可以这么搞。
选一个就这么简单,但是偶尔你还想多选几个特征,怎么搞呢?想一想以前 Numpy 教学里面的 Array 是怎么选的?
已经能选 column 了,那意味着肯定能将 Index(Row)的信息也一起考虑到数据筛选的工作当中了。
loc¶
如果你是刚从 面向 Excel
编程,或者也没怎么用过 Excel 中的函数的朋友,也可以轻松从 loc
函数中找到一丝丝熟悉的感觉。 因为这个 .loc
方法是更贴近我们人类直觉的,按照字面来选取数据块的方式。
我举个例子你就明白了,如果你对我的 Numpy教程 熟悉,你会知道,在 Numpy 中选取数据一般都是按照在维度上的排序来定位的。 比如对于你刚刚创建的 Numpy 数据 data
:
而在 DataFrame 中,同样是上述功能,你可以这么干:
咦,不知道你有没有发现,这个 "c":"d"
和 "B":"D"
明明对应的是上面 data
的 [2:3]
和 [1:3]
,但为什么它还包含了最后一位的 "d"
和 "D"
呢?这的确是 Pandas 的一个用心良苦,我猜他是为了更贴切 Excel 中的使用原则吧,想一想,如果你像下面这样, 在选择 Excel 要被筛选的数据时,从 b 选到 d,其实你是有包含 d 的。所以我说,Pandas 这么设计,原因之一也应该是为了照顾我们吧。
除了筛选一个片段,还可以像 Numpy 那样单个单个的选取。
上面这两个例子,不难看出,Pandas 选取数据的底层逻辑,和 Python Numpy 的类似,都是按维度的先后(先选第一维,再第二,以此类推), 开始选取。按数据的索引找到维度上的对应索引区域。
下面我再来整个有趣的,如果我不按字母顺序去组织 index,比如从原本的 index=abcdef
换成 index=beacdf
, 猜猜下面的这份数据索引会找到哪一份子数据?
iloc¶
看完面向 Excel 编程
,我们再来回到编程本身,用程序的思维去选取数据。这意味着什么?用最朴素的方法,也是意味着能更快找到数据位置,比如直接用位置信息来筛选。 Numpy 不就是这么干的吗?这时 .iloc
功能就派上用场了。
同样还是上面那份数据,我们走一遍 .iloc
的流程。
简直和 Numpy 的模式一模一样,就是结果中多了一个 DataFrame 的标签信息。
loc和iloc混搭¶
难免有时候,我们需要混搭 loc 和 iloc 的方式,比如我想要选取第 2 到第 4 位数据的 A C 两个特征,这时咋办? 想想 Pandas 这么牛逼,肯定有办法解决。的确,它解决的方法是采用索引转换的方式,比如我在 .loc
模式下,将序号索引转换成 .loc
的标签索引。
再看看 Column 的 labels 怎么取?
清楚了吧,用 df.index
和 df.columns
来调取到全部的标签,然后在用像 Numpy index 索引的方式把这些标签给筛选出来,放到 .loc
里面用。 那反过来,我想要找 A B 两个特征的 前两个数据,这时咋办?
同理,df.index.get_indexer(["a", "b"])
也可以这样获取到 label 对应的 index 信息。
条件过滤筛选¶
按条件过滤其实是一件很有趣的事,因为很多情况我们事先也不知道具体的 index 是什么,我们更想要从某些条件中筛选数据。 下面我举几个例子,大家应该很容易 get 到其中的奥秘。
选在 A Column 中小于 0 的那些数据
选在第一行数据不小于 -10 的数据,这里注意了你可以用两种方式,一种是 ~
来表示 非
什么什么,第二种是直接用 >=-10
来筛选。
同上面类似的,我还能用或 |
来表示 or 的意思, &
表述 and。比如选在第一行数据不小于 -10 或小于 -11 的数据
所以你看,你可以用 .loc
或者 .iloc
来做过滤处理。然后用 .loc
来做筛选。为什么用 .iloc
来筛选呢,比如下面这样:
这样写居然会导致报错,为什么呢?你分析分析,把 ~(df.iloc[0] < -10)
这个筛选条件打印出来看看它是什么值。然后想一想 .iloc
能够接受的值是啥? 想清楚了,这个问题就迎刃而解了。
Series和DataFrame类似¶
我的讲解顺序可能有点反常规,一般人可能会先从 Series 的数据筛选操作讲到 DataFrame,而我想要从你日常最常用的东西,讲到不太常用的。 从数据处理的角度,比如处理常用的 Excel,在这里的顺序, 就应该是从 DataFrame 讲到 Series。
既然二维的 DataFrame 你都已经玩过了,Series 的操作就不在话下了。
按标签筛选数据 .loc
按 index 筛选数据 .iloc
iloc
和 loc
互相混用
按条件过滤筛选
总结¶
Pandas 的数据筛选方法比 Numpy 丰富多了,介绍的篇幅也有点多,我日常用的最多的还是用条件来筛选,比如在处理机器学习的脏数据的时候,要用很多筛选逻辑。 有时甚至我会觉得 Numpy 的筛选方式不够多,专门把 Numpy 数据转换成 Pandas 数据,然后再用 Pandas 提供的丰富工具处理数据,再转回 Numpy。 相信你用熟了之后,数据处理将要简单很多。