DataFrame 数据合并方法

来源:互联网 发布:常用编程软件有哪些 编辑:程序博客网 时间:2024/05/16 05:20

DataFrame 数据合并方法

引言

Pandas 是数据分析最常用的工具包之一,DataFrame是Pandas最常用的数据结构。在使用Pandas做数据分析时会经常用到类似于数据库连表查询的需求,每次将表格读入数据库进行连表查询,未免太过繁琐。值得庆幸的是Pandas提供了强大基于DataFrame的数据合并功能。具有数据合并功能的函数一共有三个,分别是merge(),concat()和join(),下面我们将分贝进行学习。

merge()

功能解读

用于通过一个或多个键将两个数据集的行连接起来,类似于 SQL 中的 JOIN。该函数的典型应用场景是,针对同一个主键存在两张包含不同字段的表,现在我们想把他们整合到一张表里。在此典型情况下,结果集的行数并没有增加,列数则为两个元数据的列数和减去连接键的数量。对于多对多连接,结果采用的是行的笛卡尔积。

原型

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)

参数解读

  • left与right:指定要合并的DataFrame
  • how 参数指的是当左右两个对象中存在不重合的键时,取结果的方式:inner 代表交集;outer 代表并集;left 和 right 分别为取一边。
  • on 用于显示指定列名(键名),如果该列在两个对象上的列名不同,则可以通过 left_on, right_on 来分别指定。或者想直接使用行索引作为连接键的话,就将 left_index, right_index 设为 True。
  • suffixes=(‘_x’,’_y’) 指的是当左右对象中存在除连接键外的同名列时,结果集中的区分方式,可以各加一个小尾巴。
  • left_on:左则DataFrame中用作连接键的列名;这个参数在左右DataFrame列名不相同,但代表的含义相同时非常有用。
  • right_on:右则DataFrame中用作 连接键的列名
  • left_index:使用左则DataFrame中的行索引做为连接键
  • right_index:使用右则DataFrame中的行索引做为连接键
  • sort:默认为True,将合并的数据进行排序。在大多数情况下设置为False可以提高性能
  • suffixes:字符串值组成的元组,用于指定当左右DataFrame存在相同列名时在列名后面附加的后缀名称,默认为(‘_x’,’_y’)
  • copy:默认为True,总是将数据复制到数据结构中;大多数情况下设置为False可以提高性能
  • indicator:v0.17.0 版本的pandas开始还支持一个indicator的参数,如果置True的时候,输出结果会增加一列 ’ _merge’。_merge列可以取三个值: left_only 只在左表中,right_only 只在右表中,both 两个表中都有

merge 的一些特性示例

  • 默认以重叠的列名当做连接键
df1= pd.DataFrame({'key':['a','b','b'],'data1':range(3)})df2= pd.DataFrame({'key':['a','b','c'],'data2':range(3)})print(df1)print(df2)df3 = pd.merge(df1,df2)   #没有指定连接键,默认用重叠列名print(df3)
   data1 key0      0   a1      1   b2      2   b   data2 key0      0   a1      1   b2      2   c   data1 key  data20      0   a      01      1   b      12      2   b      1
  • 默认做inner连接(取key的交集)
df4 = pd.merge(df2,df1) #默认内连接,可以看见c没有连接上。print(df4)df5 = pd.merge(df2,df1,how='left') #通过how,指定连接方式,连接方式还有(left,right,outer)print(df5)
   data2 key  data10      0   a      01      1   b      12      1   b      2   data2 key  data10      0   a    0.01      1   b    1.02      1   b    2.03      2   c    NaN
  • 多键连接时将连接键组成列表传入
left=pd.DataFrame({'key1':['foo','foo','bar'],                   'key2':['one','two','one'],                   'lval':[1,2,3]})print(left)right=pd.DataFrame({'key1':['foo','foo','bar','bar'],                    'key2':['one','one','one','two'],                    'lval':[4,5,6,7]})print(right)df6 = pd.merge(left,right,on=['key1','key2'],how='outer')  #传入数组print(df6)
  key1 key2  lval0  foo  one     11  foo  two     22  bar  one     3  key1 key2  lval0  foo  one     41  foo  one     52  bar  one     63  bar  two     7  key1 key2  lval_x  lval_y0  foo  one     1.0     4.01  foo  one     1.0     5.02  foo  two     2.0     NaN3  bar  one     3.0     6.04  bar  two     NaN     7.0
  • 如果两个对象的列名不同,可以分别指定
right=pd.DataFrame({'key3':['foo','foo','bar','bar'],                    'key4':['one','one','one','two'],                    'lval':[4,5,6,7]})print(right)df7 = pd.merge(left,right,left_on='key1',right_on='key3')  #传入数组print(df7)
  key3 key4  lval0  foo  one     41  foo  one     52  bar  one     63  bar  two     7  key1 key2  lval_x key3 key4  lval_y0  foo  one       1  foo  one       41  foo  one       1  foo  one       52  foo  two       2  foo  one       43  foo  two       2  foo  one       54  bar  one       3  bar  one       65  bar  one       3  bar  two       7
  • 以索引当做连接键,使用参数left_index=true,right_index=True
left=pd.DataFrame({'key2':['one','two','one'],                   'lval':[1,2,3]},                  index=['foo','foo','bar'])print(left)right=pd.DataFrame({'key4':['one','one','one','two'],                    'lval':[4,5,6,7]},                   index=['foo','foo','bar','bar'])print(right)df8 = pd.merge(left,right,left_index=True,right_index=True)  #传入数组print(df8)
    key2  lvalfoo  one     1foo  two     2bar  one     3    key4  lvalfoo  one     4foo  one     5bar  one     6bar  two     7    key2  lval_x key4  lval_ybar  one       3  one       6bar  one       3  two       7foo  one       1  one       4foo  one       1  one       5foo  two       2  one       4foo  two       2  one       5
  • 可以一侧使用索引,一侧使用列值进行连接
left=pd.DataFrame({'key1':['foo','foo','bar'],                   'key2':['one','two','one'],                   'lval':[1,2,3]})print(left)right=pd.DataFrame({'key4':['one','one','one','two'],                    'lval':[4,5,6,7]},                   index=['foo','foo','bar','bar'])print(right)df9 = pd.merge(left,right,left_on='key1',right_index=True)  #传入数组print(df9)
  key1 key2  lval0  foo  one     11  foo  two     22  bar  one     3    key4  lvalfoo  one     4foo  one     5bar  one     6bar  two     7  key1 key2  lval_x key4  lval_y0  foo  one       1  one       40  foo  one       1  one       51  foo  two       2  one       41  foo  two       2  one       52  bar  one       3  one       62  bar  one       3  two       7

join()

功能解读

join方法提供了一个简便的方法用于将两个DataFrame中的不同的列索引合并成为一个DataFrame。其中参数的意义与merge方法基本相同,只是join方法默认为左外连接how=left。可以连接多个DataFrame。

原型

join(self, other, on=None, how='left', lsuffix='', rsuffix='',sort=False)

参数解读

  • how 和merge中的how参数一样,用来指定表合并保留数据的规则。
  • on 在实际应用中如果右表的索引值正是左表的某一列的值,这时可以通过将 右表的索引 和 左表的列 对齐合并这样灵活的方式进行合并。
  • suffix 和merge中的suffix参数一样

实例

  • how 参数的实例
data=pd.DataFrame([{"id":0,"name":'lxh',"age":20,"cp":'lm'},                   {"id":1,"name":'xiao',"age":40,"cp":'ly'},                   {"id":2,"name":'hua',"age":4,"cp":'yry'},                   {"id":3,"name":'be',"age":70,"cp":'old'}],                  index=['a','b','c','d'])data1=pd.DataFrame([{"sex":0},                    {"sex":1},                    {"sex":2}],                   index=['a','b','e'])print(data)print(data1)print ('使用默认的左连接\r\n',data.join(data1))  print ('使用右连接\r\n',data.join(data1,how="right"))print ('使用内连接\r\n',data.join(data1,how='inner'))print ('使用全外连接\r\n',data.join(data1,how='outer'))
age   cp  id  namea   20   lm   0   lxhb   40   ly   1  xiaoc    4  yry   2   huad   70  old   3    be   sexa    0b    1e    2使用默认的左连接    age   cp  id  name  sexa   20   lm   0   lxh  0.0b   40   ly   1  xiao  1.0c    4  yry   2   hua  NaNd   70  old   3    be  NaN使用右连接     age   cp   id  name  sexa  20.0   lm  0.0   lxh    0b  40.0   ly  1.0  xiao    1e   NaN  NaN  NaN   NaN    2使用内连接    age  cp  id  name  sexa   20  lm   0   lxh    0b   40  ly   1  xiao    1使用全外连接     age   cp   id  name  sexa  20.0   lm  0.0   lxh  0.0b  40.0   ly  1.0  xiao  1.0c   4.0  yry  2.0   hua  NaNd  70.0  old  3.0    be  NaNe   NaN  NaN  NaN   NaN  2.0
  • on参数的实例
left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],                    'B': ['B0', 'B1', 'B2', 'B3'],                   'key': ['K0', 'K1', 'K0', 'K1']})right = pd.DataFrame({'C': ['C0', 'C1'],                       'D': ['D0', 'D1']},                       index=['K0', 'K1'])result = left.join(right, on='key')print(result)
    A   B key   C   D0  A0  B0  K0  C0  D01  A1  B1  K1  C1  D12  A2  B2  K0  C0  D03  A3  B3  K1  C1  D1
  • 组合多个key不完全相同的dataframe
left = pd.DataFrame({'v': [1, 2, 3]}, index=['K0', 'K1', 'K2'])right = pd.DataFrame({'v': [4, 5, 6]}, index=['K0', 'K0', 'K2'])right2 = pd.DataFrame({'v': [7, 8, 9]}, index=['K1', 'K1', 'K2'])result = left.join([right, right2])print(result)
    v_x  v_y    vK0    1  4.0  NaNK0    1  5.0  NaNK1    2  NaN  7.0K1    2  NaN  8.0K2    3  6.0  9.0
  • 组合key值相同的dataframe
left = pd.DataFrame({'v1': [1, 2, 3]}, index=['K0', 'K1', 'K2'])right = pd.DataFrame({'v2': [4, 5, 6]}, index=['K0', 'K1', 'K2'])right2 = pd.DataFrame({'v3': [7, 8, 9]}, index=['K0', 'K1', 'K2'])result = left.join([right, right2])print(result)
    v1  v2  v3K0   1   4   7K1   2   5   8K2   3   6   9

concat()

功能解读

concat方法可以沿着一条轴将多个对象堆叠到一起。相当于数据库中的全连接(UNION ALL),可以指定按某个轴进行连接,也可以指定连接的方式join(outer,inner 只有这两种)。与数据库不同的时concat不会去重,要达到去重的效果可以使用drop_duplicates方法。
轴向连接 pd.concat() 就是单纯地把两个表拼在一起,这个过程也被称作连接(concatenation)、绑定(binding)或堆叠(stacking)。因此可以想见,这个函数的关键参数应该是 axis,用于指定连接的轴向。在默认的 axis=0 情况下,pd.concat([obj1,obj2])函数的效果与 obj1.append(obj2) 是相同的;而在 axis=1 的情况下,pd.concat([df1,df2],axis=1)的效果与 pd.merge(df1,df2,left_index=True,right_index=True,how='outer') 是相同的。
可以理解为 concat 函数使用索引作为“连接键”。

原型

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

参数解读

  • objs 就是需要连接的对象集合,series,dataframe或者是panel构成的序列list;
  • axis 需要合并链接的轴,0是行,1是列
  • join 连接的方式 inner,或者outer

实例

纵向表连接

  • 相同column的表首尾相接
import pandas as pddf1 = 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])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])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])  frames = [df1, df2, df3]result = pd.concat(frames)print(result)
      A    B    C    D0    A0   B0   C0   D01    A1   B1   C1   D12    A2   B2   C2   D23    A3   B3   C3   D34    A4   B4   C4   D45    A5   B5   C5   D56    A6   B6   C6   D67    A7   B7   C7   D78    A8   B8   C8   D89    A9   B9   C9   D910  A10  B10  C10  D1011  A11  B11  C11  D11
  • axis=0时等价于append函数。append是series和dataframe的方法,使用它就是默认沿着列进行拼接(axis = 0,列对齐)
    A   B   C   D0  A0  B0  C0  D01  A1  B1  C1  D12  A2  B2  C2  D23  A3  B3  C3  D34  A4  B4  C4  D45  A5  B5  C5  D56  A6  B6  C6  D67  A7  B7  C7  D7
  • keys参数可以用来给合并后的表增加key来区分不同的表数据来源
result = pd.concat(frames, keys=['x', 'y', 'z'])
  A    B    C    Dx 0    A0   B0   C0   D0  1    A1   B1   C1   D1  2    A2   B2   C2   D2  3    A3   B3   C3   D3y 4    A4   B4   C4   D4  5    A5   B5   C5   D5  6    A6   B6   C6   D6  7    A7   B7   C7   D7z 8    A8   B8   C8   D8  9    A9   B9   C9   D9  10  A10  B10  C10  D10  11  A11  B11  C11  D11
  • 传入字典来增加分组键
pieces = {'x': df1, 'y': df2, 'z': df3}result = pd.concat(pieces)print(result)
        A    B    C    Dx 0    A0   B0   C0   D0  1    A1   B1   C1   D1  2    A2   B2   C2   D2  3    A3   B3   C3   D3y 4    A4   B4   C4   D4  5    A5   B5   C5   D5  6    A6   B6   C6   D6  7    A7   B7   C7   D7z 8    A8   B8   C8   D8  9    A9   B9   C9   D9  10  A10  B10  C10  D10  11  A11  B11  C11  D11
  • 无视index的concat。如果两个表的index都没有实际含义,使用ignore_index参数,True,合并的两个表就睡根据列字段对齐,然后合并。最后再重新整理一个新的index。
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])df4 = pd.DataFrame({'B': ['B2', 'B3','B6', 'B7'],                    'D': ['D2', 'D3','D6', 'D7'],                    'F': ['D2', 'D3','D6', 'D7'],},result = pd.concat([df1, df4],ignore_index=True)print(result)
     A   B    C   D    F0   A0  B0   C0  D0  NaN1   A1  B1   C1  D1  NaN2   A2  B2   C2  D2  NaN3   A3  B3   C3  D3  NaN2  NaN  B2  NaN  D2   D23  NaN  B3  NaN  D3   D36  NaN  B6  NaN  D6   D6

横向表拼接(行对齐)

  • 当axis = 1的时候,concat就是按照索引行对齐,然后将不同列名称的两张表合并
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])df4 = pd.DataFrame({'B': ['B2', 'B3','B6', 'B7'],                    'D': ['D2', 'D3','D6', 'D7'],                    'F': ['D2', 'D3','D6', 'D7'],},                     index=[2, 3, 6, 7])result = pd.concat([df1, df4], axis=1)print(result)
     A    B    C    D    B    D    F0   A0   B0   C0   D0  NaN  NaN  NaN1   A1   B1   C1   D1  NaN  NaN  NaN2   A2   B2   C2   D2   B2   D2   D23   A3   B3   C3   D3   B3   D3   D36  NaN  NaN  NaN  NaN   B6   D6   D67  NaN  NaN  NaN  NaN   B7   D7   D7
  • 加上join参数的属性,如果为‘inner’得到的是两表的交集,如果是outer,得到的是两表的并集。
result = pd.concat([df1, df4], axis=1, join='inner')print(result)
    A   B   C   D   B   D   F2  A2  B2  C2  D2  B2  D2  D23  A3  B3  C3  D3  B3  D3  D3
  • 如果有join_axes的参数传入,可以指定根据那个轴来对齐数据 .
    例如根据df1表对齐数据,就会保留指定的df1表的轴,然后将df4的表与之拼接。相当于左连接。
result = pd.concat([df1, df4], axis=1, join_axes=[df1.index])print(result)
    A   B   C   D    B    D    F0  A0  B0  C0  D0  NaN  NaN  NaN1  A1  B1  C1  D1  NaN  NaN  NaN2  A2  B2  C2  D2   B2   D2   D23  A3  B3  C3  D3   B3   D3   D3

在dataframe中加入新的行

append方法可以将 series 和 字典构成的数据作为dataframe的新一行插入。如果遇到两张表的列字段本来就不一样,但又想将两个表合并,其中无效的值用nan来表示。那么可以使用ignore_index来实现。

s2 = pd.Series(['X0', 'X1', 'X2', 'X3'], index=['A', 'B', 'C', 'D'])result = df1.append(s2, ignore_index=True)print(result)dicts = [{'A': 1, 'B': 2, 'C': 3, 'X': 4},{'A': 5, 'B': 6, 'C': 7, 'Y': 8}] result = df1.append(dicts, ignore_index=True)print(result)
    A   B   C   D0  A0  B0  C0  D01  A1  B1  C1  D12  A2  B2  C2  D23  A3  B3  C3  D34  X0  X1  X2  X3    A   B   C    D    X    Y0  A0  B0  C0   D0  NaN  NaN1  A1  B1  C1   D1  NaN  NaN2  A2  B2  C2   D2  NaN  NaN3  A3  B3  C3   D3  NaN  NaN4   1   2   3  NaN  4.0  NaN5   5   6   7  NaN  NaN  8.0

参考文章:
1.【pandas】[3] DataFrame 数据合并,连接(merge,join,concat)
2.Pandas数据合并
3.pandas 之 concat
4.PANDAS 数据合并与重塑(concat篇)
5.PANDAS 数据合并与重塑(join/merge篇)

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 遗产继承后户口没地迁出怎么办 安徽蒙城怎么办去韩国的签证的 夜间有人私自收停车费应该怎么办 上次摸不到环尾丝这次摸到了怎么办 法院判决书下来后对方不给钱怎么办 法院判决书下来了钱还保全么怎么办 深圳路边泊车不知道泊车编号怎么办 当事人进拘留所了我的工资怎么办 昆明公租房住满5年后怎么办 昆明公租房房子到期缴纳金怎么办 看守所犯人银行卡里钱没用完怎么办 中国邮政迟迟没有把信件寄到怎么办 拘留15天放出来还不肯还钱怎么办 人死在拘留所不让看监控怎么办 家人吸毒可他又不愿强戒怎么办 容留他人吸毒时签了强戒怎么办 拘留后发现被拘留是人大代表怎么办 执行局要拘留人找不到人怎么办 开设赌场罪拘留37天了该怎么办 对治安处罚光罚款不拘留怎么办 打架和解后警察不给消案怎么办 12个人片诈骗刑拘了28天怎么办 交警拘留几天后还是没钱赔偿怎么办 平安车主信用卡车牌号填错了怎么办 起诉借钱的人逮起来了怎么办 在法院查不到坐牢人的档案怎么办 人被冤枉敲诈勒索进看守所了怎么办 打架被拘留孩子怎么办三周了 技师被拘留她的家人该怎么办 我是担保人贷款人跑了我该怎么办 公司依旷工理由辞退我该怎么办 试工两天被辞退了不发工资怎么办 员工在单位被打监控调不出来怎么办 老师罚做60张试卷家长该怎么办 孩子在幼儿园被老师打该怎么办 孩子被孩子打了老师该怎么办? 法院判决书下来后看守所不收怎么办 因病看守所不收押发院判了怎么办 现在显示还在看守所羁押需要怎么办 嫖了N多年丈夫让我怎么办 预约考试的登录密码忘了怎么办