import numpy as np
import pandas as pdPandas 中提供了 merge 函数实现关系型合并。
df1.merge(df2, how='inner', on=None, left_on=None, right_on=None,
left_index=False, right_index=False, sort=False,
suffixes=('_x', '_y'), copy=None, indicator=False, validate=None)主要参数含义:
df2:待合并的 DataFrame 或者 Serieshow:合并方式left:左连接,合并后显示 df1 的所有行right:右连接,合并后显示 df2 的所有行outer:外连接,合并后显示 df1、df2 的所有行inner:内连接,合并后显示 df1、df2 的共有行cross:交叉连接,合并后显示 df1、df2 的笛卡尔积
on:列名或者索引名,df1 和 df2 合并的键left_on、right_on:当 df1 和 df2 待合并的键在表中的名称不一样时,可分别指定left_index、right_index:布尔变量,是否使用索引进行合并suffixes:列表类型。如果两张表中有相同的列名,suffixes为合并表的列名提供了后缀
# create some toy data
df1 = pd.DataFrame({'Date': pd.date_range('2023-08-01', periods=5),
'Company': ['A', 'B', 'C', 'D', 'E'],
'Close': [20, 23, 21, 22, 20]})
df2 = pd.DataFrame({'Date': pd.date_range('2023-08-03', periods=5),
'Firm': ['C', 'D', 'E', 'F', 'G'],
'Volume': [100, 101, 120, 110, 105]})df1| Date | Company | Close | |
|---|---|---|---|
| 0 | 2023-08-01 | A | 20 |
| 1 | 2023-08-02 | B | 23 |
| 2 | 2023-08-03 | C | 21 |
| 3 | 2023-08-04 | D | 22 |
| 4 | 2023-08-05 | E | 20 |
df2| Date | Firm | Volume | |
|---|---|---|---|
| 0 | 2023-08-03 | C | 100 |
| 1 | 2023-08-04 | D | 101 |
| 2 | 2023-08-05 | E | 120 |
| 3 | 2023-08-06 | F | 110 |
| 4 | 2023-08-07 | G | 105 |
merge 默认使用内连接(inner),如果不指定合并的键,默认使用两张表中共同的列作合并,df1 和 df2 共同的列是 date,合并后显示共有的 date:
df1.merge(df2)| Date | Company | Close | Firm | Volume | |
|---|---|---|---|---|---|
| 0 | 2023-08-03 | C | 21 | C | 100 |
| 1 | 2023-08-04 | D | 22 | D | 101 |
| 2 | 2023-08-05 | E | 20 | E | 120 |
使用 left_on 和 right_on 参数可以指定两张表做合并的键,下面指定使用 df1 中的 Company 和 df2 中的 Firm 来做合并:
df1.merge(df2,
left_on='Company',
right_on='Firm')| Date_x | Company | Close | Date_y | Firm | Volume | |
|---|---|---|---|---|---|---|
| 0 | 2023-08-03 | C | 21 | 2023-08-03 | C | 100 |
| 1 | 2023-08-04 | D | 22 | 2023-08-04 | D | 101 |
| 2 | 2023-08-05 | E | 20 | 2023-08-05 | E | 120 |
由于 df1 和 df2 中都有 Date 这一列,为了加以区分,Pandas 自动给两张表中的 Date 加了后缀,我们可以使用 suffixes 参数来自定义后缀:
df1.merge(df2,
left_on='Company',
right_on='Firm',
suffixes=['_1', '_2'])| Date_1 | Company | Close | Date_2 | Firm | Volume | |
|---|---|---|---|---|---|---|
| 0 | 2023-08-03 | C | 21 | 2023-08-03 | C | 100 |
| 1 | 2023-08-04 | D | 22 | 2023-08-04 | D | 101 |
| 2 | 2023-08-05 | E | 20 | 2023-08-05 | E | 120 |
但是既然两张表里都有 Date 这一列,最好的方式是使用多键合并:
df1.merge(df2,
left_on=['Date', 'Company'],
right_on=['Date','Firm'])| Date | Company | Close | Firm | Volume | |
|---|---|---|---|---|---|
| 0 | 2023-08-03 | C | 21 | C | 100 |
| 1 | 2023-08-04 | D | 22 | D | 101 |
| 2 | 2023-08-05 | E | 20 | E | 120 |
使用 how 参数可以指定合并的方式,left 表示左连接,合并后显示 df1 的所有行,df2 中没有 2023-08-01 和 2023-08-02 两天,则对应的 Firm 和 Volume 显示为空值。
df1.merge(df2, how='left')| Date | Company | Close | Firm | Volume | |
|---|---|---|---|---|---|
| 0 | 2023-08-01 | A | 20 | NaN | NaN |
| 1 | 2023-08-02 | B | 23 | NaN | NaN |
| 2 | 2023-08-03 | C | 21 | C | 100.0 |
| 3 | 2023-08-04 | D | 22 | D | 101.0 |
| 4 | 2023-08-05 | E | 20 | E | 120.0 |
right 表示右连接,合并后显示 df2 的所有行:
df1.merge(df2, how='right')| Date | Company | Close | Firm | Volume | |
|---|---|---|---|---|---|
| 0 | 2023-08-03 | C | 21.0 | C | 100 |
| 1 | 2023-08-04 | D | 22.0 | D | 101 |
| 2 | 2023-08-05 | E | 20.0 | E | 120 |
| 3 | 2023-08-06 | NaN | NaN | F | 110 |
| 4 | 2023-08-07 | NaN | NaN | G | 105 |
outer 表示外连接,合并后显示 df1 和 df2 的所有行:
df1.merge(df2, how='outer')| Date | Company | Close | Firm | Volume | |
|---|---|---|---|---|---|
| 0 | 2023-08-01 | A | 20.0 | NaN | NaN |
| 1 | 2023-08-02 | B | 23.0 | NaN | NaN |
| 2 | 2023-08-03 | C | 21.0 | C | 100.0 |
| 3 | 2023-08-04 | D | 22.0 | D | 101.0 |
| 4 | 2023-08-05 | E | 20.0 | E | 120.0 |
| 5 | 2023-08-06 | NaN | NaN | F | 110.0 |
| 6 | 2023-08-07 | NaN | NaN | G | 105.0 |
cross 表示交叉合并,合并后显示 df1 和 df2 的笛卡尔积:
df1.merge(df2, how='cross')| Date_x | Company | Close | Date_y | Firm | Volume | |
|---|---|---|---|---|---|---|
| 0 | 2023-08-01 | A | 20 | 2023-08-03 | C | 100 |
| 1 | 2023-08-01 | A | 20 | 2023-08-04 | D | 101 |
| 2 | 2023-08-01 | A | 20 | 2023-08-05 | E | 120 |
| 3 | 2023-08-01 | A | 20 | 2023-08-06 | F | 110 |
| 4 | 2023-08-01 | A | 20 | 2023-08-07 | G | 105 |
| 5 | 2023-08-02 | B | 23 | 2023-08-03 | C | 100 |
| 6 | 2023-08-02 | B | 23 | 2023-08-04 | D | 101 |
| 7 | 2023-08-02 | B | 23 | 2023-08-05 | E | 120 |
| 8 | 2023-08-02 | B | 23 | 2023-08-06 | F | 110 |
| 9 | 2023-08-02 | B | 23 | 2023-08-07 | G | 105 |
| 10 | 2023-08-03 | C | 21 | 2023-08-03 | C | 100 |
| 11 | 2023-08-03 | C | 21 | 2023-08-04 | D | 101 |
| 12 | 2023-08-03 | C | 21 | 2023-08-05 | E | 120 |
| 13 | 2023-08-03 | C | 21 | 2023-08-06 | F | 110 |
| 14 | 2023-08-03 | C | 21 | 2023-08-07 | G | 105 |
| 15 | 2023-08-04 | D | 22 | 2023-08-03 | C | 100 |
| 16 | 2023-08-04 | D | 22 | 2023-08-04 | D | 101 |
| 17 | 2023-08-04 | D | 22 | 2023-08-05 | E | 120 |
| 18 | 2023-08-04 | D | 22 | 2023-08-06 | F | 110 |
| 19 | 2023-08-04 | D | 22 | 2023-08-07 | G | 105 |
| 20 | 2023-08-05 | E | 20 | 2023-08-03 | C | 100 |
| 21 | 2023-08-05 | E | 20 | 2023-08-04 | D | 101 |
| 22 | 2023-08-05 | E | 20 | 2023-08-05 | E | 120 |
| 23 | 2023-08-05 | E | 20 | 2023-08-06 | F | 110 |
| 24 | 2023-08-05 | E | 20 | 2023-08-07 | G | 105 |