小白學 Python 數據分析(13):Pandas (十二)數據表拼接

人生苦短,我用 Python

前文傳送門:

小白學 Python 數據分析(1):數據分析基礎

小白學 Python 數據分析(2):Pandas (一)概述

小白學 Python 數據分析(3):Pandas (二)數據結構 Series

小白學 Python 數據分析(4):Pandas (三)數據結構 DataFrame

小白學 Python 數據分析(5):Pandas (四)基礎操作(1)查看數據

小白學 Python 數據分析(6):Pandas (五)基礎操作(2)數據選擇

小白學 Python 數據分析(7):Pandas (六)數據導入

小白學 Python 數據分析(8):Pandas (七)數據預處理

小白學 Python 數據分析(9):Pandas (八)數據預處理(2)

小白學 Python 數據分析(10):Pandas (九)數據運算

小白學 Python 數據分析(11):Pandas (十)數據分組

小白學 Python 數據分析(12):Pandas (十一)數據透視表(pivot_table)

引言

說到數據表拼接,就不得不提一下 SQL ,對於熟悉 SQL 的同學來講,這並不是一個難以理解的概念,數據表之間的關係可以分為以下這三種:

一對一

兩個表之間的公共列是一對一的。

這裡的示例我們就不用圖片了,直接使用程式碼來做展示,原因嘛就是小編懶的畫了:

import pandas as pd    df1 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet1')  print(df1)    # 輸出內容      編號  姓名  分數  0  100  小明  96  1  200  小紅  48  2  300  小王  72  3  400  小剛  72    df2 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet2')  print(df2)    # 輸出內容      編號  班級  0  100   1  1  200   2  2  300   3  3  400   4

這裡可以很直觀的看到,這兩個表的編號是公共列,並且唯一對應。

如果我們要講這兩個表進行連接操作,需要使用 merge() 方法:

print(pd.merge(df1, df2))    # 輸出內容      編號  姓名  分數  班級  0  100  小明  96   1  1  200  小紅  48   2  2  300  小王  72   3  3  400  小剛  72   4

在我們使用 merge() 方法的時候, merge() 方法會自動尋找兩個表中的公共列,並且自動的進行對應操作。

一對多

兩個表之間的公共列不是一對一的,而是其中一個表的公共列是唯一的,另一個表的公共列則會有重複的數據。

import pandas as pd    df1 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet1')  print(df1)    # 輸出內容      編號  姓名  分數  0  100  小明  96  1  200  小紅  48  2  300  小王  72  3  400  小剛  72    df3 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet3')  print(df3)    # 輸出內容      編號   分數  0  100  101  1  100  102  2  100  103  3  100  104  4  200  201  5  200  202  6  300  301  7  400  401

從上面這兩個 df 中可以看到, df1 中的編號在 df3 中會對應多條數據,我們在對這兩個 df 進行連接操作的時候,需要使用屬性 on 指明判斷的條件:

print(pd.merge(df1, df3, on='編號'))    # 輸出內容      編號  姓名  分數_x  分數_y  0  100  小明    96   101  1  100  小明    96   102  2  100  小明    96   103  3  100  小明    96   104  4  200  小紅    48   201  5  200  小紅    48   202  6  300  小王    72   301  7  400  小剛    72   401

多對多

兩個表之間的公共列都是會有重複數據的,相當於是多個一對多。

注意理解多個一對多,這裡的邏輯稍微有點繞,小編在第一次接觸 SQL 的時候實際上是無法理解的。

我們這裡新建一個 df4 ,新增一個編號為 100 的小黑,還是通過編號對 df4 和 df3 進行連接操作:

df4 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet4')  print(df4)    # 輸出結果      編號  姓名   分數  0  100  小明   96  1  100  小黑  100  2  200  小紅   48  3  300  小王   72  4  400  小剛   72    print(pd.merge(df4, df3, on='編號'))       編號  姓名  分數_x  分數_y  0   100  小明    96   101  1   100  小明    96   102  2   100  小明    96   103  3   100  小明    96   104  4   100  小黑   100   101  5   100  小黑   100   102  6   100  小黑   100   103  7   100  小黑   100   104  8   200  小紅    48   201  9   200  小紅    48   202  10  300  小王    72   301  11  400  小剛    72   401

連接方式

學過 SQL 的同學都知道, SQL 中連接分為內連接、左連接、右連接和外連接,同樣在 Pandas 也是一樣的。

內連接

內連接就是取兩個表中公共的部分,我們重新創建一個 df5 ,在 df5 中只有編號 100 和 200 能和前面的數據保持一致:

df5 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet5')  print(df5)    # 輸出結果      編號        姓名   分數  0  100        小明   96  1  100        小黑  100  2  200        小紅   48  3  600  想不出來叫啥了1  600  4  700  想不出來叫啥了2  700    # 內連接  print(pd.merge(df5, df3, on='編號', how='inner'))    # 輸出結果      編號  姓名  分數_x  分數_y  0  100  小明    96   101  1  100  小明    96   102  2  100  小明    96   103  3  100  小明    96   104  4  100  小黑   100   101  5  100  小黑   100   102  6  100  小黑   100   103  7  100  小黑   100   104  8  200  小紅    48   201  9  200  小紅    48   202

這裡 how 屬性是用來指定連接類型的。

左連接

左連接就是已左表為基礎,右表像左表上拼數據:

# 左連接  print(pd.merge(df5, df3, on='編號', how='left'))    # 輸出結果       編號        姓名  分數_x   分數_y  0   100        小明    96  101.0  1   100        小明    96  102.0  2   100        小明    96  103.0  3   100        小明    96  104.0  4   100        小黑   100  101.0  5   100        小黑   100  102.0  6   100        小黑   100  103.0  7   100        小黑   100  104.0  8   200        小紅    48  201.0  9   200        小紅    48  202.0  10  600  想不出來叫啥了1   600    NaN  11  700  想不出來叫啥了2   700    NaN

可以看到,在 df5 中,編號 600 和 700 的兩條數據在 df3 中沒有,所以 分數_y 的值為 NaN 。

右連接

右連接正好和上面的左連接相反,已右表為基礎,左表往右表上拼數據:

# 右連接  print(pd.merge(df5, df3, on='編號', how='right'))    # 輸出結果       編號   姓名   分數_x  分數_y  0   100   小明   96.0   101  1   100   小黑  100.0   101  2   100   小明   96.0   102  3   100   小黑  100.0   102  4   100   小明   96.0   103  5   100   小黑  100.0   103  6   100   小明   96.0   104  7   100   小黑  100.0   104  8   200   小紅   48.0   201  9   200   小紅   48.0   202  10  300  NaN    NaN   301  11  400  NaN    NaN   401

外連接

外連接就是兩個表的並集:

# 外連接  print(pd.merge(df5, df3, on='編號', how='outer'))    # 輸出結果       編號        姓名   分數_x   分數_y  0   100        小明   96.0  101.0  1   100        小明   96.0  102.0  2   100        小明   96.0  103.0  3   100        小明   96.0  104.0  4   100        小黑  100.0  101.0  5   100        小黑  100.0  102.0  6   100        小黑  100.0  103.0  7   100        小黑  100.0  104.0  8   200        小紅   48.0  201.0  9   200        小紅   48.0  202.0  10  600  想不出來叫啥了1  600.0    NaN  11  700  想不出來叫啥了2  700.0    NaN  12  300       NaN    NaN  301.0  13  400       NaN    NaN  401.0

縱向拼接

顧名思義,縱向拼接就是在縱向上對兩個表進行拼接,當然這需要兩個表具有相同的結構,前面我們介紹的拼接方式都在橫向上進行拼接。

這裡我們再加入一個 df6 ,使用 df5 和 df6 演示縱向拼接,在 Pandas 中使用縱向拼接使用的方法是 concat()

df6 = pd.read_excel("table_join_exp.xlsx", sheet_name='Sheet6')  print(df6)    # 輸出結果      編號       姓名   分數  0  800  起個名字好難啊  100  1  900  起個名字真的難  200    # 縱向拼接  print(pd.concat([df5, df6]))    # 輸出結果      編號        姓名   分數  0  100        小明   96  1  100        小黑  100  2  200        小紅   48  3  600  想不出來叫啥了1  600  4  700  想不出來叫啥了2  700  0  800   起個名字好難啊  100  1  900   起個名字真的難  200

當我們使用 concat() 以後,發現索引還是保留了原有的索引,看著很不舒服,這時我們可以設置參數 ignore_index ,讓其不在保留原有索引,而是生成新的索引:

print(pd.concat([df5, df6], ignore_index=True))    # 輸出結果      編號        姓名   分數  0  100        小明   96  1  100        小黑  100  2  200        小紅   48  3  600  想不出來叫啥了1  600  4  700  想不出來叫啥了2  700  5  800   起個名字好難啊  100  6  900   起個名字真的難  200

本篇的分享到這裡就算結束,如果有 SQL 基礎的同學看起來應該毫無壓力,沒有基礎的同學推薦自己動手試一下,很多看著不是很理解的東西一動手就立馬打通任督二脈。

示例程式碼

老規矩,所有的示例程式碼都會上傳至程式碼管理倉庫 Github 和 Gitee 上,方便大家取用。

示例程式碼-Github

示例程式碼-Gitee