天天看點

inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

文章目錄

  • 三個函數的差別
    • concat()
    • append()
    • merge()
  • 三個函數各自的拓展用法
    • concat()
      • 連接配接多個DataFrame
      • 設定特定的鍵(key)
      • 橫向合并兩個DataFrame
    • append()
      • 連接配接多個DataFrame
    • merge()
      • 指定兩個列名連接配接DataFrame
      • merge()的四種連接配接方式

1. 三個函數的差別

concat(), append(), merge()一般都是用來連接配接兩個或者多個DataFrame對象。其中, concat(), append()預設用來縱向連接配接DataFrame對象, merge()用來橫向連接配接DataFrame對象。

接下來我們來看看具體的例子。

1.1 concat()

concat()預設情況下是縱向連接配接兩個DataFrame:

# 初始化df1
            
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
# 初始化df2
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
                        'B': ['B4', 'B5', 'B6', 'B7'],
                        'C': ['C4', 'C5', 'C6', 'C7'],
                        'D': ['D4', 'D5', 'D6', 'D7']})
df2           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
# concat : 縱向連接配接df1和df2。
result = pd.concat([df1, df2])
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

我們看到df1, df2縱向合并在了一起。但也注意到, 因為concat()保留了每個子DataFrame的index, 是以合并之後的DataFrame中, 每個index出現了兩次。

我們可以通過設定ignore_index=False來解決這個問題:

result = pd.concat([df1, df2], ignore_index=True)
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

可以看到, 設定了ignore_index=True之後, 合并之後的DataFrame對index重新進行了排序。

1.2 append()

append()的預設操作效果跟concat()相同, 都是實作兩個DataFrame的縱向連接配接。事實上可以把它看做concat()的早期版本:

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                        'B': ['B0', 'B1', 'B2', 'B3'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']})
 df1           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
                        'B': ['B4', 'B5', 'B6', 'B7'],
                        'C': ['C4', 'C5', 'C6', 'C7'],
                        'D': ['D4', 'D5', 'D6', 'D7']})
df2           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
result = df1.append(df2)
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

可以看到我們得到了跟concat()預設操作同樣的結果。因為append()也保留了每個子DataFrame的index, 是以合并之後的DataFrame中, 每個index出現了兩次。

我們同樣可以通過設定ignore_index=False來解決這個問題:

result = df1.append(df2, ignore_index=True)
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

1.3 merge()

merge()的預設操作是橫向連接配接兩個DataFrame對象:

left = pd.DataFrame({'key': ['K0', 'K1', 'K2'],
                     'A': ['A0', 'A1', 'A2'],
                     'B': ['B0', 'B1', 'B2']})
left           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
right = pd.DataFrame({'key': ['K1', 'K2', 'K3'],
                       'C': ['C1', 'C2', 'C3'],
                       'D': ['D1', 'D2', 'D3']}) 
right           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
#  橫向合并left和right兩個子DataFrame。
## on='key' :  把兩個子DataFrame中key列相同的值連接配接到一行上。
result = pd.merge(left, right, on='key')
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

從上面的結果可以看出, merge()方法把兩個子DataFrame中key列相同的值連接配接到了一行上, 并且删去了key列值不相同的行。

如果想保留key列值不相同的行, 可以添加上how='outer'參數:

# how: 指定兩個子DataFrame的連接配接方式, 
result = pd.merge(left, right, on='key', how='outer')
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

2. 三個函數各自的拓展用法

2.1 concat()

  • 2.1.1 連接配接多個DataFrame

concat()可以一次性連接配接3個或者3個以上的DataFrame:

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                        'B': ['B0', 'B1', 'B2', 'B3'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']})
 df1           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
                        'B': ['B4', 'B5', 'B6', 'B7'],
                        'C': ['C4', 'C5', 'C6', 'C7'],
                        'D': ['D4', 'D5', 'D6', 'D7']})
df2           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
                     'B': ['B8', 'B9', 'B10', 'B11'],
                      'C': ['C8', 'C9', 'C10', 'C11'],
                      'D': ['D8', 'D9', 'D10', 'D11']})
df3           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
result = pd.concat([df1, df2, df3])
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
  • 2.1.2 設定特定的鍵(key)

有時候我們需要區分合并之後的DataFrame裡, 哪些資料是來自df1的,哪些資料是來自df2的。這個時候我們可以給它們設定一個特定的鍵(key), 相當于給它們起個名字, 這樣我們就可以把它們區分開來了。

# 為每個子DataFrame設定一個特定的鍵(key)
result = pd.concat([df1, df2], keys=['df1', 'df2'])
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

可以看到, 在合并後的DataFrame裡, 我們用key把每個子DataFrame的資料辨別了出來。

我們可以通過下面的方式取用某個子DataFrame的資料:

result.loc['df1']           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
  • 2.1.3 橫向合并兩個DataFrame

預設情況下, concat()縱向合并兩個子DataFrame, 但通過設定axis=1參數之後, 我們也可以橫向合并兩個DataFrame。

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                        'B': ['B0', 'B1', 'B2', 'B3'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']})
 df1           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
# 準備一組新的資料df4
df4 = pd.DataFrame({'B': ['B2', 'B3', 'B6', 'B7'],
                     'D': ['D2', 'D3', 'D6', 'D7'],
                     'F': ['F2', 'F3', 'F6', 'F7']},
                    index=[2, 3, 6, 7])
df4           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
result = pd.concat([df1, df4], axis=1)
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

從上面的結果可以看到, 設定了axis=1之後, df1和df4兩個DataFrame橫向地結合在了一起。兩個DataFrame有着相同index的行連成了一行, index不相同的行各自占一行的内容。

如果隻想保留有着相同index的行, 可以添加上join=‘inner’參數:

result = pd.concat([df1, df4], axis=1, join='inner')
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

如果想保留某個子DataFrame的index所在的行, 比如df1中index為0-3的行, 可以加上join_axes=[df1.index]參數:

result = pd.concat([df1, df4], axis=1, join_axes=[df1.index])
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

2.2 append()

  • 2.2.1 連接配接多個DataFrame

和concat()一樣, append()也可以一次性連接配接3個或者3個以上的DataFrame:

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                        'B': ['B0', 'B1', 'B2', 'B3'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']})
 df1           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
                        'B': ['B4', 'B5', 'B6', 'B7'],
                        'C': ['C4', 'C5', 'C6', 'C7'],
                        'D': ['D4', 'D5', 'D6', 'D7']})
df2merge()           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
                     'B': ['B8', 'B9', 'B10', 'B11'],
                      'C': ['C8', 'C9', 'C10', 'C11'],
                      'D': ['D8', 'D9', 'D10', 'D11']})
df3           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
result = df1.append([df2, df3])
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

2.3 merge()

  • 2.3.1 指定兩個列名連接配接DataFrame

我們可以在on參數裡指定兩個或者兩個以上的列名對DataFrame進行連接配接:

left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
                         'key2': ['K0', 'K1', 'K0', 'K1'],
                         'A': ['A0', 'A1', 'A2', 'A3'],
                         'B': ['B0', 'B1', 'B2', 'B3']})
left           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
                          'key2': ['K0', 'K0', 'K0', 'K0'],
                          'C': ['C0', 'C1', 'C2', 'C3'],
                          'D': ['D0', 'D1', 'D2', 'D3']})
right           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
result = pd.merge(left, right, on=['key1', 'key2'])
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

在上面的例子裡, 我們在on參數裡設定了key1, key2兩個值, 于是在連接配接left和right兩個DataFrame的時候, 會把key1, key2都相等的行連在一起, 而key1, key2不完全相等的行則會被舍棄掉。

  • 2.3.2 merge()的四種連接配接方式

merge()的how參數可以設定DataFrame的四種連接配接方式:左連接配接(left), 右連接配接(right), 外連接配接(outer), 内連接配接(inner)。

内連接配接(inner)是merge()的預設連接配接方式, 當how中不設定任何參數的時候, merge()用的是内連接配接(inner)方式。 也就是我們在上面的例子中所看到的, key值不完全相同的行便不會顯示在最終的結果裡 :

left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
                         'key2': ['K0', 'K1', 'K0', 'K1'],
                         'A': ['A0', 'A1', 'A2', 'A3'],
                         'B': ['B0', 'B1', 'B2', 'B3']})
left           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
                          'key2': ['K0', 'K0', 'K0', 'K0'],
                          'C': ['C0', 'C1', 'C2', 'C3'],
                          'D': ['D0', 'D1', 'D2', 'D3']})
right           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法
result = pd.merge(left, right, on=['key1', 'key2'],
                 how='inner')
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

外連接配接(outer)則會保留兩個DataFrame中所有的行:

result = pd.merge(left, right, on=['key1', 'key2'],
                  how='outer')
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

左連接配接(left)則會保留左邊的子DataFrame中所有的行:

result = pd.merge(left, right, on=['key1', 'key2'],
                  how='left')
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

右連接配接(right)則會保留右邊的子DataFrame中所有的行:

result = pd.merge(left, right, on=['key1', 'key2'],
                  how='right')
result           
inner join 和join的差別_pandas中concat(), append(), merge()的差別和用法

以上便是本篇文章的内容。

參考資料:

https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html

繼續閱讀