前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Pandas学习笔记02-数据合并

Pandas学习笔记02-数据合并

作者头像
可以叫我才哥
发布2021-08-05 11:18:48
3.8K0
发布2021-08-05 11:18:48
举报
文章被收录于专栏:可以叫我才哥

第一章可前往查看:《Pandas学习笔记01-基础知识

pandas对象中的数据可以通过一些方式进行合并: pandas.concat可以沿着一条轴将多个对象堆叠到一起; pandas.merge可根据一个或多个键将不同DataFrame中的行连接起来。

这部分,我觉得pandas官网资料介绍的太香了,直接搬运过来吧。

1.concat

concat函数可以在两个维度上对数据进行拼接,默认纵向拼接(axis=0),拼接方式默认外连接(outer)

纵向拼接通俗来讲就是按行合并,横向拼接通俗来讲就是按列合并; 外连接通俗来说就是取所有的表头字段或索引字段,内连接通俗来说就是只取各表都有的表头字段或索引字段。

先简单看个例子吧~

代码语言:javascript
复制
In [1]: df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
   ...:                     'B': ['B0', 'B1', 'B2', 'B3'],
   ...:                     'C': ['C0', 'C1', 'C2', 'C3'],
   ...:                     'D': ['D0', 'D1', 'D2', 'D3']},
   ...:                     index=[0, 1, 2, 3])

In [2]: df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
   ...:                     'B': ['B4', 'B5', 'B6', 'B7'],
   ...:                     'C': ['C4', 'C5', 'C6', 'C7'],
   ...:                     'D': ['D4', 'D5', 'D6', 'D7']},
   ...:                     index=[4, 5, 6, 7])

In [3]: df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
   ...:                     'B': ['B8', 'B9', 'B10', 'B11'],
   ...:                     'C': ['C8', 'C9', 'C10', 'C11'],
   ...:                     'D': ['D8', 'D9', 'D10', 'D11']},
   ...:                     index=[8, 9, 10, 11])  

In [4]: df = [df1,df2,df3]
In [5]: result = pd.concat(df)                   

合并演示

pd.concat(objs, axis=0, join='outer', ignore_index=False, keys=None,levels=None, names=None, verify_integrity=False, copy=True)

objs:需要用于连接合并的对象列表 axis:连接的方向,默认为0(按行),按列为1 join:连接的方式,默认为outer,可选inner只取交集 ignore_index:合并后的数据索引重置,默认为False,可选True keys:列表或数组,也可以是元组的数组,用来构造层次结构索引 levels:指定用于层次化索引各级别上的索引,在有keys值时 names:用于创建分层级别名称,在有keys和levels时 verify_integrity:检查连接对象中新轴是否重复,若是则异常,默认为False允许重复 copy:默认为True,如果是False,则不会复制不必要的可以提高效率

1.1.设置keys值
代码语言:javascript
复制
In [6]: result = pd.concat(df, keys=['x', 'y', 'z'])

设置keys值 我们还可以通过字典形式传递keys参数(以下代码结果 和上述一致):

代码语言:javascript
复制
In [7]: pieces = {'x': df1, 'y': df2, 'z': df3}
In [8]: result = pd.concat(pieces)

我们还可以指定keys值进行数据合并:

代码语言:javascript
复制
In [9]: result = pd.concat(pieces, keys=['z', 'y'])

指定keys值数据合并 以上我们可以看到,设定keys值后,合并后的数据多了一层索引,我们可以直接通过这一层索引选择整块数据:

代码语言:javascript
复制
In [10]: result.loc['y']
Out[11]: 
    A   B   C   D
4  A4  B4  C4  D4
5  A5  B5  C5  D5
6  A6  B6  C6  D6
7  A7  B7  C7  D7
1.2.按列合并axis=1

默认情况下,join='outer',合并时索引全部保留,对于不存在值的部分会默认赋NaN。

代码语言:javascript
复制
In [12]: df4 = pd.DataFrame({'B': ['B2', 'B3', 'B6', 'B7'],
    ...:                    'D': ['D2', 'D3', 'D6', 'D7'],
    ...:                    'F': ['F2', 'F3', 'F6', 'F7']},
    ...:                     index=[2, 3, 6, 7])

In [13]: result = pd.concat([df1, df4], axis=1,sort=False)

按列合并 对于按照列合并数据时,如果我们希望只保留第一份数据下的索引,可以通过如下两种方式实现:

代码语言:javascript
复制
#①合并后只取第一份数据的索引
In [14]: pd.concat([df1, df4], axis=1).reindex(df1.index)
Out[15]: 
    A   B   C   D    B    D    F
0  A0  B0  C0  D0  NaN  NaN  NaN
1  A1  B1  C1  D1  NaN  NaN  NaN
2  A2  B2  C2  D2   B2   D2   F2
3  A3  B3  C3  D3   B3   D3   F3
#②对第二份数据设置索引为第一份部分索引
In [16]: pd.concat([df1, df4.reindex(df1.index)], axis=1)
Out[17]: 
    A   B   C   D    B    D    F
0  A0  B0  C0  D0  NaN  NaN  NaN
1  A1  B1  C1  D1  NaN  NaN  NaN
2  A2  B2  C2  D2   B2   D2   F2
3  A3  B3  C3  D3   B3   D3   F3
1.3.内连接join='inner'

内连接就是选取交集部分的索引或列名

代码语言:javascript
复制
In [18]: result = pd.concat([df1, df4], axis=1, join='inner')

内连接

1.4.忽略索引ignore_index=True

很多时候需要合并的数据存在索引重叠的情况,对于很多没有实际意义的索引(比如单纯的默认索引0到n-1),我们可以设定忽略索引从而创建新的0到m-1的索引。

代码语言:javascript
复制
In [19]: result = pd.concat([df1, df4], ignore_index=True, sort=False)

忽略索引

1.5.DataFrame与Series合并

Series与DataFrame合并时,会将Series转化为DataFrame的一列,该列名为Series的名称。

代码语言:javascript
复制
In [20]: s1 = pd.Series(['x0','x1','x2','x3'],name = 'x')
In [21]: result = pd.concat([df1,s1],axis=1)

混合数据合并 若Series未进行命名,则合并后的列名为连续的编号。

代码语言:javascript
复制
In [22]: s2 = pd.Series(['-0','-1','-2','-3'])
In [23]: result = pd.concat([df1,s2,s2,s2], axis=1)

Series未命令则连续编号 我们同样可以通过使用ignore_index = True删除并重新进行列名称编号。

代码语言:javascript
复制
In [24]: result = pd.concat([df1, s1], axis=1, ignore_index=True)

重置列名称

1.6.行数据追加到数据帧

这样做的效率一般,使用append方法,可以将Series或字典数据添加到DataFrame。 Series数据追加到数据帧

代码语言:javascript
复制
In [25]: s2 = pd.Series(['X0', 'X1', 'X2', 'X3'], index=['A', 'B', 'C', 'D'])
In [26]: result = df1.append(s2, ignore_index=True)

行数据追加到数据帧 字典数据追加到数据帧

代码语言:javascript
复制
In [27]: dicts = [{'A': 1, 'B': 2, 'C': 3, 'X': 4},
    ...:          {'A': 5, 'B': 6, 'C': 7, 'Y': 8}]
In [28]: result = df1.append(dicts, ignore_index=True, sort=False)

字典数据追加到数据帧

2.merge

merge可根据一个或多个键(列)相关同DataFrame中的拼接起来。SQL或其他关系型数据库的用户对此应该会比较熟悉,因为它实现的就是数据库的join操作。

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,left_index=False, right_index=False, sort=True, suffixes=('_x', '_y'), copy=True, indicator=False,validate=None)

left:参与合并的左侧数据 right:参与合并的右侧数据 how:合并类型:inner(默认内连接)、outer(外连接)、left(左连接)、right(右连接) on:用于连接的列名,默认为左右侧数据共有的列名,指定时需要为左右侧数据都存在的列名 left_on:左侧数据用于连接的列 right_on:右侧数据用于连接的列 left_index:将左侧索引作为连接的列 right_index:将右侧索引作为连接的列 sort:排序,默认为True,设置为False可提高性能 suffixes:默认为('_x', '_y'),可以自定义如('date_x','date_y') copy:默认为True,如果是False,则不会复制不必要的可以提高效率 indicator:指示器,设置为True时会新增一列标识行数据存在于哪侧数据 validate:字符串,如果指定则会检测合并的数据是否满足指定类型

validate 类型说明: “one_to_one” or “1:1”: checks if merge keys are unique in both left and right datasets. “one_to_many” or “1:m”: checks if merge keys are unique in left dataset. “many_to_one” or “m:1”: checks if merge keys are unique in right dataset. “many_to_many” or “m:m”: allowed, but does not result in checks.

先看个简单的例子

代码语言:javascript
复制
In [29]: result = df1.append(dicts, ignore_index=True, sort=False)
In [30]: left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
    ...:                              'A': ['A0', 'A1', 'A2', 'A3'],
    ...:                              'B': ['B0', 'B1', 'B2', 'B3']})
    ...: 
    ...: right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
    ...:                               'C': ['C0', 'C1', 'C2', 'C3'],
    ...:                               'D': ['D0', 'D1', 'D2', 'D3']})
In [31]: result = pd.merge(left, right, on='key')

在这里插入图片描述

2.1.链接方式how=' '

left左连接 只保留左侧数据有的索引

代码语言:javascript
复制
In [32]: left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
    ...:                      'key2': ['K0', 'K1', 'K0', 'K1'],
    ...:                      'A': ['A0', 'A1', 'A2', 'A3'],
    ...:                      'B': ['B0', 'B1', 'B2', 'B3']})
    ...: 
    ...: 
In [33]: right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
    ...:                       'key2': ['K0', 'K0', 'K0', 'K0'],
    ...:                       'C': ['C0', 'C1', 'C2', 'C3'],
    ...:                       'D': ['D0', 'D1', 'D2', 'D3']})
In [34]: result = pd.merge(left, right, how='left', on=['key1', 'key2'])

left左连接 right右连接 只保留右侧数据有的索引

代码语言:javascript
复制
In [35]: result = pd.merge(left, right, how='right', on=['key1', 'key2'])

right右连接 outer外连接 外连接会保留左右两侧全部的索引

代码语言:javascript
复制
In [36]: result = pd.merge(left, right, how='outer', on=['key1', 'key2'])

outer外连接 inner内连接 外连接只保留左右两侧均有的索引,这个也是默认的连接形式

代码语言:javascript
复制
In [37]: result = pd.merge(left, right, how='inner', on=['key1', 'key2'])

inner内连接

2.2.validate检查重复键

validate参数可以指定一对一、一对多、多对一和多对多的情况,若不满足对应情况则在合并时会发生异常。

代码语言:javascript
复制
In [38]: left = pd.DataFrame({'A' : [1,2], 'B' : [1, 2]})
In [39]: right = pd.DataFrame({'A' : [4,5,6], 'B': [2, 2, 2]})

以上left和right有重复项,都包含A和B名称的列,默认情况下是会根据两个都有的列名进行合并,若设置validate='one_to_one'则会报错。

代码语言:javascript
复制
In [40]: result
Out[41]: 
Empty DataFrame
Columns: [A, B]
Index: []

In [42]: result = pd.merge(left, right,on = 'B',how ='outer',validate='one_to_one')
    "Merge keys are not unique in right dataset; "
MergeError: Merge keys are not unique in right dataset; not a one-to-one merge

若我们设置validate='one_to_many'则可正常合并。

代码语言:javascript
复制
In [43]: pd.merge(left, right, on='B', how='outer', validate="one_to_many")
Out[44]: 
   A_x  B  A_y
0    1  1  NaN
1    2  2  4.0
2    2  2  5.0
3    2  2  6.0

In [45]: pd.merge(left, right, on='B', how='outer', validate="many_to_many")
Out[46]: 
   A_x  B  A_y
0    1  1  NaN
1    2  2  4.0
2    2  2  5.0
3    2  2  6.0
2.3.indicator合并指示器

默认情况下,indicator为False,若我们设置为True,则会在合并数据后新增一列标识

代码语言:javascript
复制
In [47]: df1 = pd.DataFrame({'col1': [0, 1], 'col_left': ['a', 'b']})
In [94]: df2 = pd.DataFrame({'col1': [1, 2, 2], 'col_right': [2, 2, 2]})

In [48]: df1
Out[49]: 
   col1 col_left
0     0        a
1     1        b

In [50]: df2
Out[51]: 
   col1  col_right
0     1          2
1     2          2
2     2          2
In [52]: pd.merge(df1, df2, on='col1', how='outer', indicator=True)
Out[53]: 
   col1 col_left  col_right      _merge
0     0        a        NaN   left_only
1     1        b        2.0        both
2     2      NaN        2.0  right_only
3     2      NaN        2.0  right_only

我们也可以对indicator辅助列进行命名,通过传递参数形式。

代码语言:javascript
复制
In [54]: pd.merge(df1, df2, on='col1', how='outer', indicator='辅助标识器')
Out[55]: 
   col1 col_left  col_right       辅助标识器
0     0        a        NaN   left_only
1     1        b        2.0        both
2     2      NaN        2.0  right_only
3     2      NaN        2.0  right_only
2.4.left_on和right_on

当我们想合并的两个数据出现没有公共列名的情况,可以用left_on和right_on分别指定左右两侧数据用于匹配的列。

代码语言:javascript
复制
In [56]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
     ...:                      'B': ['B0', 'B1', 'B2', 'B3'],
     ...:                      'key': ['K0', 'K1', 'K0', 'K1']})
     ...: 
     ...: 
In [57]: right = pd.DataFrame({'C': ['C0', 'C1'],
     ...:                       'D': ['D0', 'D1'],
     ...:                       'key2': ['K0', 'K1']})

In [58]: result = pd.merge(left, right, left_on='key', right_on='key2',how='left', sort=False)
In [59]: result
Out[60]: 
    A   B key   C   D key2
0  A0  B0  K0  C0  D0   K0
1  A1  B1  K1  C1  D1   K1
2  A2  B2  K0  C0  D0   K0
3  A3  B3  K1  C1  D1   K1    

3.join

join可以将两个没用共同列名的数据进行快速合并,默认是保留被被合并的数据索引

代码语言:javascript
复制
In [61]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
     ...:                      'B': ['B0', 'B1', 'B2']},
     ...:                     index=['K0', 'K1', 'K2'])

In [62]: right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
     ...:                       'D': ['D0', 'D2', 'D3']},
     ...:                     index=['K0', 'K2', 'K3'])

In [63]: result = left.join(right)

join简单案例 join接受的参数有how、on和suffix等 以下两个表达式是等效的:

代码语言:javascript
复制
>>>left.join(right, on=key_or_keys)
>>>pd.merge(left, right, left_on=key_or_keys, right_index=True,
      how='left', sort=False)

比如:

join

代码语言:javascript
复制
In [64]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
     ...:                      'B': ['B0', 'B1', 'B2', 'B3'],
     ...:                      'key': ['K0', 'K1', 'K0', 'K1']})
     ...: 
     ...: 
In [65]: right = pd.DataFrame({'C': ['C0', 'C1'],
     ...:                       'D': ['D0', 'D1']},
     ...:                       index=['K0', 'K1'])

In [66]: result = left.join(right, on='key')
In [67]: result
Out[68]: 
    A   B key   C   D
0  A0  B0  K0  C0  D0
1  A1  B1  K1  C1  D1
2  A2  B2  K0  C0  D0
3  A3  B3  K1  C1  D1

In [69]: result = pd.merge(left, right, left_on='key', right_index=True,how='left', sort=False)
In [70]: result
Out[71]: 
    A   B key   C   D
0  A0  B0  K0  C0  D0
1  A1  B1  K1  C1  D1
2  A2  B2  K0  C0  D0
3  A3  B3  K1  C1  D1

参考资料 ①https://pandas.pydata.org/docs/user_guide/merging.html#timeseries-friendly-merging

嗨,你还在看吗?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 可以叫我才哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.concat
    • 1.1.设置keys值
      • 1.2.按列合并axis=1
        • 1.3.内连接join='inner'
          • 1.4.忽略索引ignore_index=True
            • 1.5.DataFrame与Series合并
              • 1.6.行数据追加到数据帧
              • 2.merge
                • 2.1.链接方式how=' '
                  • 2.2.validate检查重复键
                    • 2.3.indicator合并指示器
                      • 2.4.left_on和right_on
                      • 3.join
                      相关产品与服务
                      数据库
                      云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档