数据合并
pandas包中,进行数据合并有join()
、merge()
、concat()
, append()
四种方法。它们的区别是:
- df.join() 相同行索引的数据被合并在一起,因此拼接后的行数不会增加(可能会减少)、列数增加;
- df.merge()通过指定的列索引进行合并,行列都有可能增加;merge也可以指定行索引进行合并;
- pd.concat()通过axis参数指定在水平还是垂直方向拼接;
- df.append()在DataFrame的末尾添加一行或多行;大致等价于
pd.concat([df1,df2],axis=0,join='outer')
。
import numpy as np
import pandas as pd
df1 = pd.DataFrame(np.arange(1,9).reshape(2, 4),index=["A","B"],columns=list("abcd"))
df1
df2 = pd.DataFrame(np.zeros((3,3)),index=list("ABC"),columns=list("xyz"))
df2
| x | y | z |
---|
A | 0.0 | 0.0 | 0.0 |
---|
B | 0.0 | 0.0 | 0.0 |
---|
C | 0.0 | 0.0 | 0.0 |
---|
1 df.join()按相同index拼接列
- 相同行索引的不同列被合并在一起;
- 左拼接(how=‘left’)时,other中与DataFrame中不同的行索引会被忽略(如C行只在df2中,合并后的df1_new中没有C行);
- 没同时在两个对象中的位置,会用NaN填充。如:左拼接(how=‘left’)时,DataFrame中有,但other中没有的行索引会保留,并用NaN填充;
- 要合并的两个DataFrame对象默认不能有相同的列索引。若有相同列索引,需要通过lsuffix或rsuffix参数为相同列指定后缀,否则会报错。
源码:
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
参数 | 说明 |
---|
other | 右表, DataFrame, Series, or list of DataFrame |
on | 关联字段, 是关联index的 |
how | 拼接方式,默认left,{‘left’, ‘right’, ‘outer’, ‘inner’} |
lsuffix | 左表相同列索引的后缀 |
rsuffix | 右表相同列索引的后缀 |
sort | 根据连接键对合并后的数据进行排列,默认为False |
1.1 how参数取值含义示意图:
how=‘inner’ 内连接:A.join(B, how=‘inner’),取同时出现在AB中的index:

how=‘outer’ 外连接:A.join(B, how=‘outer’),取AB中的index的并集:

how=‘right’ 右连接:A.join(B, how=‘right’),B中的所有index,独自出现在A中的index被忽略:
how=‘left’ 右连接:A.join(B, how=‘left’),A中所有的index,独自出现在B中的index被忽略:
1.2 有相同行索引且没有重复列索引时:
how参数默认left,代表左连接,以左边的DataFrame的index为拼接依据;
print("df1.index:\n", df1.index)
print()
df1_new = df1.join(df2)
df1_new
df1.index:
Index(['A', 'B'], dtype='object')
| a | b | c | d | x | y | z |
---|
A | 1 | 2 | 3 | 4 | 0.0 | 0.0 | 0.0 |
---|
B | 5 | 6 | 7 | 8 | 0.0 | 0.0 | 0.0 |
---|
df2.join(df1)
| x | y | z | a | b | c | d |
---|
A | 0.0 | 0.0 | 0.0 | 1.0 | 2.0 | 3.0 | 4.0 |
---|
B | 0.0 | 0.0 | 0.0 | 5.0 | 6.0 | 7.0 | 8.0 |
---|
C | 0.0 | 0.0 | 0.0 | NaN | NaN | NaN | NaN |
---|
1.3 有相同行索引和列索引
df = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3', 'K4', 'K5'],
'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']})
df
| key | A |
---|
0 | K0 | A0 |
---|
1 | K1 | A1 |
---|
2 | K2 | A2 |
---|
3 | K3 | A3 |
---|
4 | K4 | A4 |
---|
5 | K5 | A5 |
---|
other = pd.DataFrame({'key': ['K0', 'K1', 'K2'],
'B': ['B0', 'B1', 'B2']})
other
列索引’key’在左右表中都存在,必须指定左右表的后缀,可以2个参数一起使用,或只指定左表或右表的后缀
df.join(other, lsuffix='_left', rsuffix='_ritht')
| key_left | A | key_ritht | B |
---|
0 | K0 | A0 | K0 | B0 |
---|
1 | K1 | A1 | K1 | B1 |
---|
2 | K2 | A2 | K2 | B2 |
---|
3 | K3 | A3 | NaN | NaN |
---|
4 | K4 | A4 | NaN | NaN |
---|
5 | K5 | A5 | NaN | NaN |
---|
df.join(other, lsuffix='_left')
| key_left | A | key | B |
---|
0 | K0 | A0 | K0 | B0 |
---|
1 | K1 | A1 | K1 | B1 |
---|
2 | K2 | A2 | K2 | B2 |
---|
3 | K3 | A3 | NaN | NaN |
---|
4 | K4 | A4 | NaN | NaN |
---|
5 | K5 | A5 | NaN | NaN |
---|
df.join(other, rsuffix='_ritht')
| key | A | key_ritht | B |
---|
0 | K0 | A0 | K0 | B0 |
---|
1 | K1 | A1 | K1 | B1 |
---|
2 | K2 | A2 | K2 | B2 |
---|
3 | K3 | A3 | NaN | NaN |
---|
4 | K4 | A4 | NaN | NaN |
---|
5 | K5 | A5 | NaN | NaN |
---|
1.4 on参数指定关联字段
默认情况下,左连接(how=‘left’)时,当想拼接的两个表中,虽然行索引不同,但右表的行索引与左表中某一列的值有相同值时,可以 左表.join(右表, on='右表列索引')
来进行拼接。
other.set_index(keys=['key'])
df
| key | A |
---|
0 | K0 | A0 |
---|
1 | K1 | A1 |
---|
2 | K2 | A2 |
---|
3 | K3 | A3 |
---|
4 | K4 | A4 |
---|
5 | K5 | A5 |
---|
df.join(other.set_index(keys=['key']), on='key')
| key | A | B |
---|
0 | K0 | A0 | B0 |
---|
1 | K1 | A1 | B1 |
---|
2 | K2 | A2 | B2 |
---|
3 | K3 | A3 | NaN |
---|
4 | K4 | A4 | NaN |
---|
5 | K5 | A5 | NaN |
---|
2 df.merge()按列索引拼接列
2.1 两表中有共同列索引时:
nan代替没同时出现的元素
源码:
DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes='_x', '_y', copy=True, indicator=False, validate=None)
参数 | 说明 |
---|
right | 右表, DataFrame, Series, or list of DataFrame |
how | 拼接方式,默认inner,{‘left’, ‘right’, ‘outer’, ‘inner’} |
on | 默认None,自动根据相同列拼接。关联字段, 是关联columns的,必须同时存在于2个表中 |
left_on | 默认None,左表中用作连接键的列索引 |
right_on | 默认None,右表中用作连接键的列索引 |
left_index | 默认Flase,是否将左表中的行索引用作连接键 |
right_index | 默认Flase,是否将右表中的行索引用作连接键 |
sort | 根据连接键对合并后的数据进行排列,默认为Flase |
df1
df3 = pd.DataFrame(np.zeros((3,3)),columns=list("fax"))
df3
| f | a | x |
---|
0 | 0.0 | 0.0 | 0.0 |
---|
1 | 0.0 | 0.0 | 0.0 |
---|
2 | 0.0 | 0.0 | 0.0 |
---|
2.1.1 默认内连接 how=‘inner’
df1
df1.merge(df3, on="a")
df3 = pd.DataFrame(np.arange(12).reshape((3,4)),columns=list("faxy"))
df3
df1.merge(df3, on="a")
2.1.2 外连接 how=‘outer’
df1.merge(df3, on="a", how="outer")
| a | b | c | d | f | x | y |
---|
0 | 1 | 2.0 | 3.0 | 4.0 | 0 | 2 | 3 |
---|
1 | 5 | 6.0 | 7.0 | 8.0 | 4 | 6 | 7 |
---|
2 | 9 | NaN | NaN | NaN | 8 | 10 | 11 |
---|
2.1.3 左连接 how=‘left’
df1.merge(df3, on="a", how="left")
2.1.4 右连接 how=‘right’
df1.merge(df3, on="a", how="right")
| a | b | c | d | f | x | y |
---|
0 | 1 | 2.0 | 3.0 | 4.0 | 0 | 2 | 3 |
---|
1 | 5 | 6.0 | 7.0 | 8.0 | 4 | 6 | 7 |
---|
2 | 9 | NaN | NaN | NaN | 8 | 10 | 11 |
---|
2.2 当2表中没有共同列索引:
t1.merge(t2, left_on="O", right_on="X")
- 通过left_on指定t1中的按照O列进行合并
- 通过right_on指定t2中的按照X列进行合并
- O列和X列中必须有相同的元素,比如下例中的元素"c"
- NAN代替没同时出现的元素
t1 = pd.DataFrame(np.ones((3, 4)), index=list("ABC"), columns=list("MNOP"))
for i in t1.index:
t1.loc[i, "O"] = i.lower()
t1
| M | N | O | P |
---|
A | 1.0 | 1.0 | a | 1.0 |
---|
B | 1.0 | 1.0 | b | 1.0 |
---|
C | 1.0 | 1.0 | c | 1.0 |
---|
t2 = pd.DataFrame(np.zeros((2, 5)), index=list("AB"), columns=list("VWXYZ"))
t2.loc["A", "X"] = "c"
t2.loc["B", "X"] = "d"
t2
| V | W | X | Y | Z |
---|
A | 0.0 | 0.0 | c | 0.0 | 0.0 |
---|
B | 0.0 | 0.0 | d | 0.0 | 0.0 |
---|
2.2.1 how='inner’交集
t1.merge(t2, left_on="O", right_on="X")
| M | N | O | P | V | W | X | Y | Z |
---|
0 | 1.0 | 1.0 | c | 1.0 | 0.0 | 0.0 | c | 0.0 | 0.0 |
---|
2.2.2 how='outer’并集
t1.merge(t2, left_on="O", right_on="X", how="outer")
| M | N | O | P | V | W | X | Y | Z |
---|
0 | 1.0 | 1.0 | a | 1.0 | NaN | NaN | NaN | NaN | NaN |
---|
1 | 1.0 | 1.0 | b | 1.0 | NaN | NaN | NaN | NaN | NaN |
---|
2 | 1.0 | 1.0 | c | 1.0 | 0.0 | 0.0 | c | 0.0 | 0.0 |
---|
3 | NaN | NaN | NaN | NaN | 0.0 | 0.0 | d | 0.0 | 0.0 |
---|
2.2.3 how='left’左连接
t1.shape, t2.shape
((3, 4), (2, 5))
t1.merge(t2, left_on="O", right_on="X", how="left")
| M | N | O | P | V | W | X | Y | Z |
---|
0 | 1.0 | 1.0 | a | 1.0 | NaN | NaN | NaN | NaN | NaN |
---|
1 | 1.0 | 1.0 | b | 1.0 | NaN | NaN | NaN | NaN | NaN |
---|
2 | 1.0 | 1.0 | c | 1.0 | 0.0 | 0.0 | c | 0.0 | 0.0 |
---|
2.2.4 how='right’右连接
t1.merge(t2, left_on="O", right_on="X", how="right")
| M | N | O | P | V | W | X | Y | Z |
---|
0 | 1.0 | 1.0 | c | 1.0 | 0.0 | 0.0 | c | 0.0 | 0.0 |
---|
1 | NaN | NaN | NaN | NaN | 0.0 | 0.0 | d | 0.0 | 0.0 |
---|
2.3 存在相同列,但指定以其他不同列拼接时,suffixes参数为相同列增加后缀
df1 = pd.DataFrame({'lkey': ['foo', 'bar', 'baz', 'foo'],
'value': [1, 2, 3, 5]})
df1
| lkey | value |
---|
0 | foo | 1 |
---|
1 | bar | 2 |
---|
2 | baz | 3 |
---|
3 | foo | 5 |
---|
df2 = pd.DataFrame({'rkey': ['foo', 'bar', 'baz', 'foo'],
'value': [5, 6, 7, 8]})
df2
| rkey | value |
---|
0 | foo | 5 |
---|
1 | bar | 6 |
---|
2 | baz | 7 |
---|
3 | foo | 8 |
---|
df1.merge(df2)
df1.merge(df2, left_on='lkey', right_on='rkey')
| lkey | value_x | rkey | value_y |
---|
0 | foo | 1 | foo | 5 |
---|
1 | foo | 1 | foo | 8 |
---|
2 | foo | 5 | foo | 5 |
---|
3 | foo | 5 | foo | 8 |
---|
4 | bar | 2 | bar | 6 |
---|
5 | baz | 3 | baz | 7 |
---|
2.4 指定以相同行索引进行拼接,等价于join()方法:
df1
| lkey | value |
---|
0 | foo | 1 |
---|
1 | bar | 2 |
---|
2 | baz | 3 |
---|
3 | foo | 5 |
---|
df2
| rkey | value |
---|
0 | foo | 5 |
---|
1 | bar | 6 |
---|
2 | baz | 7 |
---|
3 | foo | 8 |
---|
df1.merge(df2, left_index=True, right_index=True)
| lkey | value_x | rkey | value_y |
---|
0 | foo | 1 | foo | 5 |
---|
1 | bar | 2 | bar | 6 |
---|
2 | baz | 3 | baz | 7 |
---|
3 | foo | 5 | foo | 8 |
---|
3 按方向拼接 pd.concat()
pandas.concat(objs: Union[Iterable[FrameOrSeries], Mapping[Label, FrameOrSeries]], axis='0', join: str = "'outer'", ignore_index: bool = 'False', keys='None', levels='None', names='None', verify_integrity: bool = 'False', sort: bool = 'False', copy: bool = 'True') → FrameOrSeriesUnion
-
按方向拼接(pd.concat()按行或列进行合并,axis参数决定拼接方向)
-
pd.concat([data1, data2], axis=0) 默认axis=0,垂直方向拼接,默认join='outer’并集拼接;当join='inner’进行交集拼接时,对列索引取交集;
-
pd.concat([data1, data2], axis=1) 水平方向拼接,默认并集拼接;当join='inner’进行交集拼接时,对行索引取交集;
-
并集拼接时,若列标签均不相同,则行列标签数量均会增加,未同时存在在2个表中的字段的values为NaN;
常用参数 | 说明 |
---|
objs | 要合并的DataFrame或Series,以列表传入。如[df1, df2] |
axis | 拼接方向,{0/’index’, 1/’columns’},默认0,代表垂直方向拼接;1代表水平方向拼接 |
join | 拼接方式,默认outer并集,{‘outer’, ‘inner’} ,inner交集 |
ignore_index | 默认False,是否需要重置索引。 |
df1
| lkey | value |
---|
0 | foo | 1 |
---|
1 | bar | 2 |
---|
2 | baz | 3 |
---|
3 | foo | 5 |
---|
df2
| rkey | value |
---|
0 | foo | 5 |
---|
1 | bar | 6 |
---|
2 | baz | 7 |
---|
3 | foo | 8 |
---|
3.1 axis=0 垂直方向
3.1.1 join='outer’并集拼接
相同的字段的列被合并,不同的列也被保留,未同时出现在2表中的字段以空值NaN代替
pd.concat([df1, df2])
| lkey | value | rkey |
---|
0 | foo | 1 | NaN |
---|
1 | bar | 2 | NaN |
---|
2 | baz | 3 | NaN |
---|
3 | foo | 5 | NaN |
---|
0 | NaN | 5 | foo |
---|
1 | NaN | 6 | bar |
---|
2 | NaN | 7 | baz |
---|
3 | NaN | 8 | foo |
---|
3.1.2 join='inner’交集拼接,未重置索引
垂直交集拼接时,相同列索引的字段垂直拼接,不同列索引的字段被忽略。
pd.concat([df1, df2], join='inner')
3.1.3 join='inner’交集+重置索引ignore_index=True
pd.concat([df1, df2], join='inner', ignore_index=True)
3.2 axis=1水平方向
3.2.1 join='outer’并集拼接
水平方向并集拼接时,相同列索引被当做2个不同列保留
df1.index = [1, 2, 3, 4]
df1
| lkey | value |
---|
1 | foo | 1 |
---|
2 | bar | 2 |
---|
3 | baz | 3 |
---|
4 | foo | 5 |
---|
df2
| rkey | value |
---|
0 | foo | 5 |
---|
1 | bar | 6 |
---|
2 | baz | 7 |
---|
3 | foo | 8 |
---|
pd.concat([df1, df2], axis=1)
| lkey | value | rkey | value |
---|
0 | NaN | NaN | foo | 5.0 |
---|
1 | foo | 1.0 | bar | 6.0 |
---|
2 | bar | 2.0 | baz | 7.0 |
---|
3 | baz | 3.0 | foo | 8.0 |
---|
4 | foo | 5.0 | NaN | NaN |
---|
3.2.2 join='inner’交集拼接
pd.concat([df1, df2], axis=1, join='inner')
| lkey | value | rkey | value |
---|
1 | foo | 1 | bar | 6 |
---|
2 | bar | 2 | baz | 7 |
---|
3 | baz | 3 | foo | 8 |
---|
4 df.append()在DataFrame末尾添加行
- 和pd.concat方法的区别:
- append只能做行的拼接
- append方法是外连接
- 相同点:
- append可以支持多个DataFrame的拼接
- append大致等同于
pd.concat([df1,df2],axis=0,join='outer')
源码:
DataFrame.append(other, ignore_index=False, verify_integrity=False, sort=False)
常用参数 | 说明 |
---|
other | 要被拼接进去的对象 |
ignore_index | 是否需要重置索引,默认False不重置,会保留other的原索引; |
verify_integrity | 默认False,是否在创建具有重复项的索引时引发ValueError |
sort | 默认False,否,是否在df和other的列不对齐时,对列进行排序 |
df = pd.DataFrame([[1, 2], [3, 4]], index=[1, 2], columns=list('AB'))
df
df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AB'))
df2
df.append(df2)
df.append(df2, ignore_index=True)
上一行代码,与下面pd.concat()等价
pd.concat([df, df2], axis=0, join='outer', ignore_index=True)