DataFrame 数据合并方法

14 篇文章 2 订阅

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 key
0      0   a
1      1   b
2      2   b
   data2 key
0      0   a
1      1   b
2      2   c
   data1 key  data2
0      0   a      0
1      1   b      1
2      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  data1
0      0   a      0
1      1   b      1
2      1   b      2
   data2 key  data1
0      0   a    0.0
1      1   b    1.0
2      1   b    2.0
3      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  lval
0  foo  one     1
1  foo  two     2
2  bar  one     3
  key1 key2  lval
0  foo  one     4
1  foo  one     5
2  bar  one     6
3  bar  two     7
  key1 key2  lval_x  lval_y
0  foo  one     1.0     4.0
1  foo  one     1.0     5.0
2  foo  two     2.0     NaN
3  bar  one     3.0     6.0
4  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  lval
0  foo  one     4
1  foo  one     5
2  bar  one     6
3  bar  two     7
  key1 key2  lval_x key3 key4  lval_y
0  foo  one       1  foo  one       4
1  foo  one       1  foo  one       5
2  foo  two       2  foo  one       4
3  foo  two       2  foo  one       5
4  bar  one       3  bar  one       6
5  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  lval
foo  one     1
foo  two     2
bar  one     3
    key4  lval
foo  one     4
foo  one     5
bar  one     6
bar  two     7
    key2  lval_x key4  lval_y
bar  one       3  one       6
bar  one       3  two       7
foo  one       1  one       4
foo  one       1  one       5
foo  two       2  one       4
foo  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  lval
0  foo  one     1
1  foo  two     2
2  bar  one     3
    key4  lval
foo  one     4
foo  one     5
bar  one     6
bar  two     7
  key1 key2  lval_x key4  lval_y
0  foo  one       1  one       4
0  foo  one       1  one       5
1  foo  two       2  one       4
1  foo  two       2  one       5
2  bar  one       3  one       6
2  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  name
a   20   lm   0   lxh
b   40   ly   1  xiao
c    4  yry   2   hua
d   70  old   3    be
   sex
a    0
b    1
e    2
使用默认的左连接
    age   cp  id  name  sex
a   20   lm   0   lxh  0.0
b   40   ly   1  xiao  1.0
c    4  yry   2   hua  NaN
d   70  old   3    be  NaN
使用右连接
     age   cp   id  name  sex
a  20.0   lm  0.0   lxh    0
b  40.0   ly  1.0  xiao    1
e   NaN  NaN  NaN   NaN    2
使用内连接
    age  cp  id  name  sex
a   20  lm   0   lxh    0
b   40  ly   1  xiao    1
使用全外连接
     age   cp   id  name  sex
a  20.0   lm  0.0   lxh  0.0
b  40.0   ly  1.0  xiao  1.0
c   4.0  yry  2.0   hua  NaN
d  70.0  old  3.0    be  NaN
e   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   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
  • 组合多个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    v
K0    1  4.0  NaN
K0    1  5.0  NaN
K1    2  NaN  7.0
K1    2  NaN  8.0
K2    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  v3
K0   1   4   7
K1   2   5   8
K2   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 pd

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])


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    D
0    A0   B0   C0   D0
1    A1   B1   C1   D1
2    A2   B2   C2   D2
3    A3   B3   C3   D3
4    A4   B4   C4   D4
5    A5   B5   C5   D5
6    A6   B6   C6   D6
7    A7   B7   C7   D7
8    A8   B8   C8   D8
9    A9   B9   C9   D9
10  A10  B10  C10  D10
11  A11  B11  C11  D11
  • axis=0时等价于append函数。append是series和dataframe的方法,使用它就是默认沿着列进行拼接(axis = 0,列对齐)
    A   B   C   D
0  A0  B0  C0  D0
1  A1  B1  C1  D1
2  A2  B2  C2  D2
3  A3  B3  C3  D3
4  A4  B4  C4  D4
5  A5  B5  C5  D5
6  A6  B6  C6  D6
7  A7  B7  C7  D7
  • keys参数可以用来给合并后的表增加key来区分不同的表数据来源
result = pd.concat(frames, keys=['x', 'y', 'z'])
  A    B    C    D
x 0    A0   B0   C0   D0
  1    A1   B1   C1   D1
  2    A2   B2   C2   D2
  3    A3   B3   C3   D3
y 4    A4   B4   C4   D4
  5    A5   B5   C5   D5
  6    A6   B6   C6   D6
  7    A7   B7   C7   D7
z 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    D
x 0    A0   B0   C0   D0
  1    A1   B1   C1   D1
  2    A2   B2   C2   D2
  3    A3   B3   C3   D3
y 4    A4   B4   C4   D4
  5    A5   B5   C5   D5
  6    A6   B6   C6   D6
  7    A7   B7   C7   D7
z 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    F
0   A0  B0   C0  D0  NaN
1   A1  B1   C1  D1  NaN
2   A2  B2   C2  D2  NaN
3   A3  B3   C3  D3  NaN
2  NaN  B2  NaN  D2   D2
3  NaN  B3  NaN  D3   D3
6  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    F
0   A0   B0   C0   D0  NaN  NaN  NaN
1   A1   B1   C1   D1  NaN  NaN  NaN
2   A2   B2   C2   D2   B2   D2   D2
3   A3   B3   C3   D3   B3   D3   D3
6  NaN  NaN  NaN  NaN   B6   D6   D6
7  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   F
2  A2  B2  C2  D2  B2  D2  D2
3  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    F
0  A0  B0  C0  D0  NaN  NaN  NaN
1  A1  B1  C1  D1  NaN  NaN  NaN
2  A2  B2  C2  D2   B2   D2   D2
3  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   D
0  A0  B0  C0  D0
1  A1  B1  C1  D1
2  A2  B2  C2  D2
3  A3  B3  C3  D3
4  X0  X1  X2  X3
    A   B   C    D    X    Y
0  A0  B0  C0   D0  NaN  NaN
1  A1  B1  C1   D1  NaN  NaN
2  A2  B2  C2   D2  NaN  NaN
3  A3  B3  C3   D3  NaN  NaN
4   1   2   3  NaN  4.0  NaN
5   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篇)

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值