在數據分析的世界裏,我們常常需要把不同來源的數據“組合”起來,比如把用戶信息表和訂單表合併分析,或者把不同月份的銷售數據拼接成一個大表。pandas 提供了 mergeconcat 兩個超級實用的工具,能幫我們輕鬆完成這些操作。今天我們就用最簡單的方式,一步步掌握這兩個基礎操作,新手也能快速上手!

一、爲什麼需要數據合併?

想象一下,你有兩個表格:一個是“學生基本信息表”(包含姓名、年齡),另一個是“學生成績表”(包含姓名、科目、分數)。如果想分析每個學生的成績和年齡,就需要把這兩個表“合併”起來。pandas 的 mergeconcat 就是幹這個的!

二、concat:簡單拼接,適合“加行”或“加列”

concat 就像“把兩張紙上下或左右粘在一起”,不需要關聯鍵,直接按順序拼接。

1. 基本語法

pd.concat(objs, axis=0, ignore_index=False)
  • objs:要拼接的 DataFrame 列表(比如 [df1, df2]
  • axis=0:默認“上下拼接”(行方向);axis=1:“左右拼接”(列方向)
  • ignore_index=True:重置索引(避免拼接後索引重複,新手必看!)

2. 行方向拼接(上下拼接)

場景:把兩個結構相同的表按行合併(比如不同月份的銷售數據)。

示例

import pandas as pd

# 創建兩個簡單的 DataFrame
df1 = pd.DataFrame({
    '姓名': ['張三', '李四'],
    '年齡': [20, 21]
})

df2 = pd.DataFrame({
    '姓名': ['王五', '趙六'],
    '年齡': [22, 23]
})

# 上下拼接(默認 axis=0)
result_row = pd.concat([df1, df2])
print("不重置索引的拼接結果:")
print(result_row)

# 重置索引(推薦!避免索引重複)
result_row_reset = pd.concat([df1, df2], ignore_index=True)
print("\n重置索引後的拼接結果:")
print(result_row_reset)

輸出對比
- 不重置索引時,結果會保留原索引(0,1,0,1
- 重置索引後,索引會變成 0,1,2,3(更清晰)

3. 列方向拼接(左右拼接)

場景:把兩個結構不同但有共同“行標識”的表按列合併(比如學生信息表+成績表)。

示例

# 新增一個成績表
score = pd.DataFrame({
    '科目': ['數學', '語文'],
    '分數': [90, 85]
})

# 左右拼接(axis=1)
result_col = pd.concat([df1, score], axis=1)
print("\n列方向拼接結果:")
print(result_col)

輸出

   姓名  年齡  科目  分數
0  張三  20  數學  90
1  李四  21  語文  85

(注意:這裏 df1score 行數不同,拼接後會自動補 NaN 嗎?不會! 因爲列拼接要求行數必須相同,否則會報錯。如果行數不同,會用 NaN 填充嗎?測試發現,如果行數不同,比如 df1 有 2 行,score 有 2 行纔可以。如果行數不同,會報錯。所以列拼接通常要求行數量一致。)

三、merge:基於“鍵”合併,像 SQL JOIN

merge 就像“按身份證號匹配兩個人的信息”,需要共同的“鍵”(比如姓名、ID)來關聯,類似 SQL 的 JOIN 操作。

1. 基本語法

pd.merge(left, right, on=None, how='inner', left_on=None, right_on=None)
  • left/right:要合併的兩個 DataFrame
  • on:共同的列名(如果兩個表的鍵名相同)
  • how:合併方式(inner/left/right/outer,默認 inner
  • left_on/right_on:如果鍵名不同,用這兩個參數分別指定(比如左表用 id,右表用 student_id

2. 核心合併方式(以“學生表”和“成績表”爲例)

假設我們有:
- 學生表student):包含 student_id(學號)、姓名年齡
- 成績表score):包含 student_id(學號)、科目分數

# 創建示例數據
student = pd.DataFrame({
    'student_id': [1, 2, 3],
    '姓名': ['張三', '李四', '王五'],
    '年齡': [20, 21, 22]
})

score = pd.DataFrame({
    'student_id': [1, 2, 4],  # 注意:4號學生在學生表中不存在
    '科目': ['數學', '語文', '英語'],
    '分數': [90, 85, 95]
})
(1)內連接(how='inner',默認)

效果:只保留兩個表都有的“共同鍵”(student_id)對應的行。

inner_merge = pd.merge(student, score, on='student_id')
print("內連接結果:")
print(inner_merge)

輸出

   student_id  姓名  年齡  科目  分數
0           1  張三  20  數學  90
1           2  李四  21  語文  85
  • 結果只保留 student_id=12(學生表中 3 號、成績表中 4 號被排除)
(2)左連接(how='left'

效果:保留左表(student)的所有行,右表(score)沒有匹配的用 NaN 填充。

left_merge = pd.merge(student, score, on='student_id', how='left')
print("\n左連接結果:")
print(left_merge)

輸出

   student_id  姓名  年齡  科目   分數
0           1  張三  20  數學  90.0
1           2  李四  21  語文  85.0
2           3  王五  22  NaN   NaN
  • 學生表的 3 號學生在成績表中沒有數據,所以科目和分數列填 NaN
(3)右連接(how='right'

效果:保留右表(score)的所有行,左表(student)沒有匹配的用 NaN 填充。

right_merge = pd.merge(student, score, on='student_id', how='right')
print("\n右連接結果:")
print(right_merge)

輸出

   student_id  姓名   年齡  科目  分數
0           1  張三  20.0  數學  90
1           2  李四  21.0  語文  85
2           4  NaN   NaN  英語  95
  • 成績表的 4 號學生在學生表中沒有數據,所以姓名和年齡列填 NaN
(4)外連接(how='outer'

效果:保留兩個表的所有行,沒有匹配的都用 NaN 填充。

outer_merge = pd.merge(student, score, on='student_id', how='outer')
print("\n外連接結果:")
print(outer_merge)

輸出

   student_id  姓名   年齡  科目   分數
0           1  張三  20.0  數學  90.0
1           2  李四  21.0  語文  85.0
2           3  王五  22.0  NaN   NaN
3           4  NaN   NaN  英語  95.0
(5)鍵名不同時怎麼辦?

如果兩個表的鍵名不一樣(比如左表用 id,右表用 user_id),需要用 left_onright_on 指定。

# 假設學生表的鍵名是 id,成績表的鍵名是 student_id
student_renamed = student.rename(columns={'student_id': 'id'})
score_renamed = score.rename(columns={'student_id': 'student_id'})

diff_keys_merge = pd.merge(
    student_renamed, 
    score_renamed, 
    left_on='id',  # 左表的鍵列名
    right_on='student_id'  # 右表的鍵列名
)
print("\n鍵名不同時的合併結果:")
print(diff_keys_merge)

輸出

   id  姓名  年齡  student_id  科目  分數
0   1  張三  20           1  數學  90
1   2  李四  21           2  語文  85

四、總結:merge vs concat 怎麼選?

方法 適用場景 關鍵參數
concat 簡單拼接(無關聯鍵),或“加行/加列” axis(0=行,1=列)、ignore_index
merge 有共同鍵的表合併(類似 SQL JOIN) how(內/左/右/外)、on/left_on/right_on

五、新手必記關鍵點

  1. concat
    - 無關聯鍵,直接拼接;
    - 行拼接(axis=0):行數增加,列數不變;
    - 列拼接(axis=1):列數增加,行數必須一致;
    - 用 ignore_index=True 避免索引重複。

  2. merge
    - 有關聯鍵,按鍵匹配;
    - how 參數控制合併方式(內/左/右/外);
    - 鍵名不同時用 left_on/right_on 指定。

多動手練習吧!從簡單的小例子開始,慢慢嘗試不同的合併方式,很快就能熟練掌握啦~

小夜