融合数据 Concat 和 Merge
数据表合并的情况也不罕见,在工作学习中,肯定有需要把表合并处理的时候,比如每个班级收上来一份班级表, 年级主任需要把所有班级表合并,在统一看全年级的情况。我们今天就来见识 Pandas 里面用于合并的多样化处理方式。
日常要处理的合并情况还是相对比较简单的,但是 Pandas 提供了非常丰富的合并方案,我觉得也没必要介绍那些偏门的, 先提前知晓,下面的内容是针对我们生活中比较常见的情况,如果下面的方法不能满足你的需求, 可以来看看这份官方文档。
本节要涉及的功能:
介绍¶
最简单的拼接无非就是上下左右的拼接,但是你有没有想过,在 Pandas 的 DataFrame 中,我们还有 index 和 column 这东西的存在, 它们的存在是为了我们更好的对应上数据的 index,可以用这些 index 索引和选取数据。
那么在拼接的时候,你无时无刻也要关注对齐
的影响。我们需不需要让 index 和 column 对齐,如果对不齐,有能怎么办? 还好 Pandas 早为你想到了这些问题,也提供了很多合适的处理方案。
拼接Concat¶
注意,我都规定了这三组 df 拥有不相冲突的 index,但是相同的 column 名,我们把它们进行上下拼接看看。
假设上面是三个不同班级的学生信息,如果你还是想带上班级的索引栏,你可以给他们加上一个主 key。比如 xyz
三个不同班。
这样你索引的时候,还是可以按班级来索引。这样可以既不破坏原本的 df 结构,又不丢失不同 df 的组织状态。
pd.concat
的默认是上下拼接的,我们也可以指定进行左右拼接。
注意,我这里故意没有对齐他们的 index。 你仔细观察的话,df1
和 df4
不是完全标齐的 index 和 column, 但是他们还是可以拼接的,只是拼接的时候 pandas 会自动将缺失的部分填充成 NaN。
其实这种模式叫做 join="outer"
的方式(默认方式), 中文的话,就叫它外拼接
吧。与其对应的,只留下对齐后的 index 和 column 模式, 我们可以用内拼接
join="inner"
。
有内外拼接,说明你十分关注重组后的数据 index,但是有的时候,我们的确不会关注新数据的 index 对齐。 与其保留老数据的索引,我还不如搞一个全新索引,直接覆盖了,不管以前了。用 ignore_index
就可以。
之前讲 pandas DataFrame 结构和基础操作的时候. 同学们可能会有这样一个疑问,我们怎么像 Numpy 或者 Python List 那样,append 数据进来呢?那这节数据拼接内容就来告诉你,可以用 concat
。
我把一条新的 col X 数据拼接到了 df1 的最右边。同样,如果你要向下 append
的话,首先你要有一条对应的 Series 数据。 然后 pd.concat
时选用 axis=0
进行上下拼接。但是 Pandas 不会帮你自动判断 添加 Series
的维度信息。这里还需要你手动将 Series
转化 .to_frame()
成 df,并调整 df 的维度信息,才能正常拼接。
做一个类似 Python list append 的操作这么麻烦的吗!! 当然不是,你也可以用一个简单的 append
搞定。两者出来是一样的效果。
pd.concat()
我觉得已经能满足我们日常生活中的大部分拼接任务了。不过 Pandas 知道你肯定还有特殊需求, 比如在拼接的时候,到底要基于哪边 df 的 index?要不要添加特殊的新 col 名等等。所以它还给了一个更加细节的 pd.merge()
函数。
融合Merge¶
一般来说,如果你十分熟悉 SQL 语言那一套,merge 就非常适合你,其他的小伙伴,我觉得只有你发现 concat 不能解决你的问题的时候, 在过来看看 merge 能不能。因为 merge 还是比 concat 稍微复杂一点的。比如光是 join
的方式,就比 concat 多出了 3 种。
注意,concat
可以一次性合并多个 df,可以【左右】,也可以【上下】拼接, 但是 merge
是用来针对两张 df 做【左右】拼接的。 但是如果你真的懂 merge
的功能,也许你会更喜欢用 merge
。
重要的事说三遍,merge 只做左右拼接。左右拼接。左右拼接。
另外一点注意的:merge()
只在你指定的 col 作为 index 来合并,所以有一个 on="key"
参数。 而 concat
只在 index/column 上寻找统一索引。 merge()
和 concat()
在用法上,的确是有很大差别的。
上面只在对齐的时候基于了一个 key,如果你的数据中还有多个可以用个 key column, 你也可以传入所有你想要基于的 key 做拼接 on=["key1", "key2"]
。
对比 concat()
, 我前面也提到,merge()
在 join 的时候,方法比 concat()
多了 3 种。 下面的前两种是 concat()
和 merge()
都具备的。后面几种是 merge()
另外的。
- outer: 集合两个 df 所有 的 key
- inner: 集合两个 df 同时拥有 的 key
- left: 仅考虑左边 df 所有 的 key
- right: 仅考虑右边 df 所有 的 key
- cross: 对于两个 df key 的笛卡尔积
你在上面的 how
中填入不同的值,来试试看不同的结合效果。我在下面贴几张图,用来演示这几种不同的效果。
right
outer
inner
cross
cross 比较特别,组出来的表特别大,因为它是两个 key 的笛卡尔积,一般其实你也用不到。
merge 我就先介绍到这里,还有一些其他的参数,比如 suffixes,indicator。如果你感兴趣, 可以看到这份官方文档。
接入Join¶
明白了 merge,我就可以来说说 join 了。join 其实是 df.join()
。 但是它其实更像是 merge
和 concat
的某种结合体,merge()
是基于给定的某个 on="key"
来拼接, 而 df.join()
使用的 key 可以和 concat()
一样,都是 index,也可以像 merge()
带一个 on="key"
去使用一个 column 作为索引。
df.join()
的时候默认是使用 how="left"
的。你可以在上面尝试将 how
这个参数明确出来,写不同的 join
方式, 比如 ‘left’, ‘right’, ‘outer’, ‘inner’
。
使用 key 作为 join 依据的时候,你可以这样使用:
总结¶
今天我向大家介绍了三种 pandas 中常用来合并数据的方式,concat
,merge
,join
他们的规则还是挺多的, 我也挑了一些重要的来讲解,如果你发现上面的合并方式还不能解决你的问题, 我将文档也贴上,你可以查看一下官方的说明。