小白學 Python 資料分析(13):Pandas (十二)資料表拼接
阿新 • • 發佈:2020-03-07
![](https://cdn.geekdigging.com/python/spider-blog/Python_logo.jpg)
> 人生苦短,我用 Python
前文傳送門:
[小白學 Python 資料分析(1):資料分析基礎](https://www.geekdigging.com/2020/01/19/6719980708/)
[小白學 Python 資料分析(2):Pandas (一)概述](https://www.geekdigging.com/2020/01/20/6718497214/)
[小白學 Python 資料分析(3):Pandas (二)資料結構 Series](https://www.geekdigging.com/2020/02/04/3234667780/)
[小白學 Python 資料分析(4):Pandas (三)資料結構 DataFrame](https://www.geekdigging.com/2020/02/05/9920298470/)
[小白學 Python 資料分析(5):Pandas (四)基礎操作(1)檢視資料](https://www.geekdigging.com/2020/02/16/6852411690/)
[小白學 Python 資料分析(6):Pandas (五)基礎操作(2)資料選擇](https://www.geekdigging.com/2020/02/20/6566891797/)
[小白學 Python 資料分析(7):Pandas (六)資料匯入](https://www.geekdigging.com/2020/02/23/7355903936/)
[小白學 Python 資料分析(8):Pandas (七)資料預處理](https://www.geekdigging.com/2020/02/25/9013297409/)
[小白學 Python 資料分析(9):Pandas (八)資料預處理(2)](https://www.geekdigging.com/2020/02/27/2857868620/)
[小白學 Python 資料分析(10):Pandas (九)資料運算](https://www.geekdigging.com/2020/02/29/5808964196/)
[小白學 Python 資料分析(11):Pandas (十)資料分組](https://www.geekdigging.com/2020/03/03/5975552137/)
[小白學 Python 資料分析(12):Pandas (十一)資料透視表(pivot_table)](https://www.geekdigging.com/2020/03/04/8327177610/)
## 引言
說到資料表拼接,就不得不提一下 SQL ,對於熟悉 SQL 的同學來講,這並不是一個難以理解的概念,資料表之間的關係可以分為以下這三種:
### 一對一
兩個表之間的公共列是一對一的。
這裡的示例我們就不用圖片了,直接使用程式碼來做展示,原因嘛就是小編懶的畫了:
```python
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()` 方法:
```python
print(pd.merge(df1, df2))
# 輸出內容
編號 姓名 分數 班級
0 100 小明 96 1
1 200 小紅 48 2
2 300 小王 72 3
3 400 小剛 72 4
```
在我們使用 `merge()` 方法的時候, `merge()` 方法會自動尋找兩個表中的公共列,並且自動的進行對應操作。
### 一對多
兩個表之間的公共列不是一對一的,而是其中一個表的公共列是唯一的,另一個表的公共列則會有重複的資料。
```python
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` 指明判斷的條件:
```python
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 進行連線操作:
```python
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 能和前面的資料保持一致:
```python
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` 屬性是用來指定連線型別的。
### 左連線
左連線就是已左表為基礎,右表像左表上拼資料:
```python
# 左連線
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 。
### 右連線
右連線正好和上面的左連線相反,已右表為基礎,左表往右表上拼資料:
```python
# 右連線
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
```
### 外連線
外連線就是兩個表的並集:
```python
# 外連線
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()` :
```python
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` ,讓其不在保留原有索引,而是生成新的索引:
```python
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](https://github.com/meteor1993/python-learning/tree/master/python-data-analysis/pandas-demo "示例程式碼-Github")
[示例程式碼-Gitee](https://gitee.com/inwsy/python-learning/tree/master/python-data-analysis/pandas-demo "示例程式碼