最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Pandas多源數(shù)據(jù)整合之三大數(shù)據(jù)合并方法(Merge,Join與Concat?)詳解

 更新時間:2026年05月27日 09:13:13   作者:小莊-Python辦公  
本文介紹了Pandas中三種數(shù)據(jù)整合方法,即merge、join和concat,重點講解了merge函數(shù)的四種連接方式(內(nèi)連接、左連接、右連接、外連接)及其參數(shù)使用,希望對大家有所幫助

本節(jié)學(xué)習(xí)目標(biāo)

  • 理解數(shù)據(jù)庫連接的各種類型(inner、outer、left、right)
  • 掌握 merge 函數(shù)的全部核心參數(shù)
  • 學(xué)會使用 join 進(jìn)行基于索引的關(guān)聯(lián)
  • 掌握 concat 進(jìn)行軸向合并
  • 能夠處理多表關(guān)聯(lián)和數(shù)據(jù)對齊問題

為什么學(xué)這個?

在真實工作環(huán)境中,數(shù)據(jù)很少只存在于一張表中。以電商系統(tǒng)為例:

  • 用戶表:存儲用戶的姓名、郵箱、注冊日期
  • 訂單表:存儲訂單號、用戶 ID、下單時間、總金額
  • 產(chǎn)品表:存儲產(chǎn)品 ID、名稱、分類、單價

當(dāng)你想回答"2024年購買電子產(chǎn)品最多的用戶是誰"這個問題時,你需要同時關(guān)聯(lián)這三張表。

這正是本節(jié)的重點:多源數(shù)據(jù)整合

Pandas 提供了三種主要的數(shù)據(jù)合并方式:

  • merge —— 基于列值的關(guān)聯(lián)(類似 SQL 的 JOIN)
  • join —— 基于索引的關(guān)聯(lián)
  • concat —— 按軸方向拼接(上下或左右)

打個比方:如果說 groupby 是把數(shù)據(jù)"拆分再匯總",那么 merge/join/concat 就是把散落各處的數(shù)據(jù)"拼起來"。前者是拆解分析,后者是整合重組,兩者同等重要。

核心知識點講解

merge:基于列值的關(guān)聯(lián)

merge 是 Pandas 中最常用的數(shù)據(jù)關(guān)聯(lián)方法,它與 SQL 數(shù)據(jù)庫中的 JOIN 操作非常類似。

1. 準(zhǔn)備示例數(shù)據(jù)

import pandas as pd
import numpy as np

# 訂單表
orders = pd.DataFrame({
    '訂單ID': [1001, 1002, 1003, 1004, 1005],
    '用戶ID': [1, 2, 3, 1, 4],
    '金額': [500, 300, 800, 200, 1500],
    '日期': ['2024-01-15', '2024-02-20', '2024-03-10', '2024-04-05', '2024-05-18']
})

# 用戶表
users = pd.DataFrame({
    '用戶ID': [1, 2, 3, 5],
    '姓名': ['張三', '李四', '王五', '趙六'],
    '城市': ['北京', '上海', '廣州', '深圳']
})

# 產(chǎn)品表
products = pd.DataFrame({
    '訂單ID': [1001, 1002, 1003, 1004, 1005],
    '產(chǎn)品名': ['手機(jī)', '耳機(jī)', '電腦', '充電器', '手表'],
    '品類': ['電子產(chǎn)品', '配件', '電子產(chǎn)品', '配件', '飾品']
})

print("訂單表:")
print(orders)
print("\n用戶表:")
print(users)
print("\n產(chǎn)品表:")
print(products)

2. 內(nèi)連接(inner join)

內(nèi)連接只保留兩個表中都有的匹配行。

# 內(nèi)連接:只保留有用戶信息的訂單
result = pd.merge(orders, users, on='用戶ID', how='inner')
print("內(nèi)連接(只保留有用戶的訂單):")
print(result)

# 注意:用戶ID=4 的訂單被丟棄了(因為用戶表中沒有ID=4的用戶)
# 用戶ID=5 的趙六也被丟棄了(因為訂單表中沒有他的訂單)

Venn 圖理解:inner join 就像兩個圓圈的交集部分。

3. 左連接(left join)

左連接保留左表的所有行,右表中沒有匹配的填充 NaN。

# 左連接:保留所有訂單,匹配不到的用戶信息為 NaN
result = pd.merge(orders, users, on='用戶ID', how='left')
print("左連接(保留所有訂單):")
print(result)

# 訂單ID=1005 的訂單保留了,但用戶信息(姓名、城市)為 NaN
# 因為用戶表中沒有用戶ID=4的記錄

左連接是最常用的連接方式,因為它保證了主表(左表)的數(shù)據(jù)完整性。

4. 右連接(right join)

右連接保留右表的所有行,左表中沒有匹配的填充 NaN。

# 右連接:保留所有用戶,沒有訂單的用戶訂單信息為 NaN
result = pd.merge(orders, users, on='用戶ID', how='right')
print("右連接(保留所有用戶):")
print(result)

# 趙六(用戶ID=5)保留了,但訂單信息為 NaN
# 因為他沒有下過訂單

5. 外連接(outer join)

外連接保留兩個表的所有行,沒有匹配的填充 NaN。

# 外連接:保留所有訂單和所有用戶
result = pd.merge(orders, users, on='用戶ID', how='outer')
print("外連接(保留所有):")
print(result)

6. merge 參數(shù)詳解

# ===== on / left_on / right_on =====

# on=:兩個表的關(guān)聯(lián)列名相同
result = pd.merge(orders, users, on='用戶ID')

# left_on / right_on:關(guān)聯(lián)列名不同
users2 = pd.DataFrame({
    'ID': [1, 2, 3, 5],  # 列名不同
    '姓名': ['張三', '李四', '王五', '趙六'],
    '城市': ['北京', '上海', '廣州', '深圳']
})

result = pd.merge(
    orders, users2,
    left_on='用戶ID',    # 左表的關(guān)聯(lián)列
    right_on='ID'        # 右表的關(guān)聯(lián)列
)
print("不同列名關(guān)聯(lián):")
print(result)

# ===== suffixes:處理重名列 =====
orders2 = pd.DataFrame({
    '訂單ID': [1001, 1002],
    '金額': [500, 300],
    '更新時間': ['2024-01-15', '2024-02-20']  # 與右表有重名列
})

users3 = pd.DataFrame({
    '訂單ID': [1001, 1002],
    '金額': [550, 320],  # 重名列
    '更新時間': ['2024-01-16', '2024-02-21']  # 重名列
})

result = pd.merge(
    orders2, users3,
    on='訂單ID',
    how='left',
    suffixes=('_訂單', '_用戶')  # 自定義后綴
)
print("重名列處理:")
print(result)

# ===== indicator:顯示匹配來源 =====
result = pd.merge(orders, users, on='用戶ID', how='outer', indicator=True)
print("匹配來源:")
print(result)
# _merge 列會顯示 "both"、"left_only"、"right_only"

7. 多表關(guān)聯(lián)

# 三表關(guān)聯(lián):先關(guān)聯(lián) orders + users,再關(guān)聯(lián) products
result = pd.merge(orders, users, on='用戶ID', how='left')
result = pd.merge(result, products, on='訂單ID', how='left')
print("三表關(guān)聯(lián)結(jié)果:")
print(result)

# 鏈?zhǔn)綄懛?
result = (orders
          .merge(users, on='用戶ID', how='left')
          .merge(products, on='訂單ID', how='left'))
print("\n鏈?zhǔn)綄懛ǎ?)
print(result)

join:基于索引的關(guān)聯(lián)

join 是基于索引進(jìn)行關(guān)聯(lián)的方法。它本質(zhì)上是 merge 的便捷版本,當(dāng)你的關(guān)聯(lián)鍵是索引時,使用 join 更簡潔。

# 設(shè)置索引
orders_idx = orders.set_index('用戶ID')
users_idx = users.set_index('用戶ID')

print("orders 索引:")
print(orders_idx)
print("\nusers 索引:")
print(users_idx)

# ===== 左連接(join 默認(rèn)就是左連接)=====
result = orders_idx.join(users_idx, lsuffix='_訂單', rsuffix='_用戶')
print("join 左連接:")
print(result)

# ===== 指定連接方式 =====
result = orders_idx.join(users_idx, how='inner', lsuffix='_訂單', rsuffix='_用戶')
print("\njoin 內(nèi)連接:")
print(result)

# join 的等價 merge 寫法:
# result = pd.merge(orders, users, left_index=True, right_index=True, how='left')

concat:軸向拼接

concat 用于將多個 DataFrame 按軸方向拼接——可以是上下拼接(縱向),也可以是左右拼接(橫向)。

1. 縱向拼接(axis=0,默認(rèn))

# 兩個結(jié)構(gòu)相同的 DataFrame
df1 = pd.DataFrame({
    '姓名': ['張三', '李四'],
    '年齡': [25, 30],
    '城市': ['北京', '上海']
})

df2 = pd.DataFrame({
    '姓名': ['王五', '趙六'],
    '年齡': [28, 35],
    '城市': ['廣州', '深圳']
})

# 上下拼接
result = pd.concat([df1, df2])
print("上下拼接:")
print(result)

# 忽略原索引
result = pd.concat([df1, df2], ignore_index=True)
print("\n忽略原索引:")
print(result)

# 添加來源標(biāo)記
result = pd.concat([df1, df2], keys=['表1', '表2'])
print("\n帶來源標(biāo)記:")
print(result)

2. 橫向拼接(axis=1)

# 兩個結(jié)構(gòu)不同的 DataFrame
df_a = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6]
})

df_b = pd.DataFrame({
    'C': [7, 8, 9],
    'D': [10, 11, 12]
})

# 左右拼接
result = pd.concat([df_a, df_b], axis=1)
print("左右拼接:")
print(result)

3. concat 的數(shù)據(jù)對齊行為

# concat 會按索引對齊
df_x = pd.DataFrame({'A': [1, 2]}, index=[0, 1])
df_y = pd.DataFrame({'B': [3, 4]}, index=[1, 2])

result = pd.concat([df_x, df_y], axis=1)
print("索引對齊拼接:")
print(result)
# 輸出:
#      A    B
# 0  1.0  NaN
# 1  2.0  3.0
# 2  NaN  4.0

# inner:只保留共有的索引
result = pd.concat([df_x, df_y], axis=1, join='inner')
print("\ninner 對齊:")
print(result)
# 只保留索引 1

對比與選擇指南

方法適用場景關(guān)聯(lián)依據(jù)示例
merge表關(guān)聯(lián)(類似 SQL JOIN)列值merge(df1, df2, on='id')
join基于索引的關(guān)聯(lián)索引df1.join(df2)
concat數(shù)據(jù)追加或并排拼接軸方向concat([df1, df2])

快速決策

  • 有共同的列名做關(guān)聯(lián)?→ 用 merge
  • 索引就是關(guān)聯(lián)鍵?→ 用 join(或 merge(left_index=True, right_index=True)
  • 只是把兩個表上下或左右拼起來?→ 用 concat

數(shù)據(jù)對齊與常見問題

1. 重復(fù)列名處理

# 關(guān)聯(lián)后可能出現(xiàn)重復(fù)列
df1 = pd.DataFrame({'ID': [1, 2], 'name': ['A', 'B'], 'score': [90, 85]})
df2 = pd.DataFrame({'ID': [1, 2], 'name': ['A', 'B'], 'grade': ['A', 'B']})

result = pd.merge(df1, df2, on='ID', suffixes=('_1', '_2'))
print(result)

2. 一對多關(guān)聯(lián)

# 一個用戶對應(yīng)多個訂單(一對多)
users = pd.DataFrame({
    '用戶ID': [1, 2, 3],
    '姓名': ['張三', '李四', '王五']
})

orders = pd.DataFrame({
    '訂單ID': [101, 102, 103, 104],
    '用戶ID': [1, 1, 2, 3],  # 用戶1有兩個訂單
    '金額': [500, 300, 800, 200]
})

result = pd.merge(users, orders, on='用戶ID', how='left')
print("一對多關(guān)聯(lián):")
print(result)
# 張三會出現(xiàn)兩行,分別對應(yīng)兩個訂單

3. 多對多關(guān)聯(lián)

# 多對多關(guān)聯(lián)會產(chǎn)生笛卡爾積
df1 = pd.DataFrame({'key': ['A', 'A', 'B'], 'val1': [1, 2, 3]})
df2 = pd.DataFrame({'key': ['A', 'A', 'B'], 'val2': [4, 5, 6]})

result = pd.merge(df1, df2, on='key')
print("多對多關(guān)聯(lián)(笛卡爾積):")
print(result)
# A-A 組合產(chǎn)生 2×2=4 行
# 注意:Pandas 3.x 中多對多關(guān)聯(lián)需要顯式指定 validate 參數(shù)

實戰(zhàn)練習(xí)

練習(xí) 1:三表關(guān)聯(lián)查詢

題目:關(guān)聯(lián)學(xué)生、課程、成績?nèi)龔埍怼?/p>

# 參考答案
import pandas as pd

students = pd.DataFrame({
    '學(xué)號': [101, 102, 103, 104],
    '姓名': ['小明', '小紅', '小剛', '小麗'],
    '班級': ['一班', '二班', '一班', '三班']
})

courses = pd.DataFrame({
    '課程號': ['C01', 'C02', 'C03'],
    '課程名': ['語文', '數(shù)學(xué)', '英語'],
    '學(xué)分': [4, 5, 4]
})

grades = pd.DataFrame({
    '學(xué)號': [101, 101, 102, 102, 103, 103, 104, 104],
    '課程號': ['C01', 'C02', 'C01', 'C03', 'C02', 'C03', 'C01', 'C02'],
    '成績': [85, 90, 92, 88, 78, 82, 96, 85]
})

# 1. 關(guān)聯(lián)學(xué)生 + 成績
result = students.merge(grades, on='學(xué)號', how='left')
result = result.merge(courses, on='課程號', how='left')
print("學(xué)生-課程-成績關(guān)聯(lián):")
print(result)

# 2. 計算每個學(xué)生的平均分
avg = result.groupby(['學(xué)號', '姓名'])['成績'].mean().reset_index()
avg.columns = ['學(xué)號', '姓名', '平均分']
print("\n學(xué)生平均分:")
print(avg.round(1))

練習(xí) 2:數(shù)據(jù)拼接實踐

題目:將多個季度的數(shù)據(jù)文件合并。

# 參考答案
import pandas as pd
import numpy as np

# 模擬四個季度的數(shù)據(jù)
q1 = pd.DataFrame({
    '季度': ['Q1'] * 3,
    '產(chǎn)品': ['A', 'B', 'C'],
    '銷售額': [1000, 2000, 1500]
})

q2 = pd.DataFrame({
    '季度': ['Q2'] * 3,
    '產(chǎn)品': ['A', 'B', 'C'],
    '銷售額': [1200, 2200, 1600]
})

q3 = pd.DataFrame({
    '季度': ['Q3'] * 3,
    '產(chǎn)品': ['A', 'B', 'C'],
    '銷售額': [1100, 2100, 1700]
})

q4 = pd.DataFrame({
    '季度': ['Q4'] * 3,
    '產(chǎn)品': ['A', 'B', 'C'],
    '銷售額': [1300, 2300, 1800]
})

# 縱向拼接
df = pd.concat([q1, q2, q3, q4], ignore_index=True)
print("年度合并數(shù)據(jù):")
print(df)

# 計算年度匯總
summary = df.groupby('產(chǎn)品')['銷售額'].agg(['sum', 'mean']).reset_index()
summary.columns = ['產(chǎn)品', '年銷售額', '季均銷售額']
print("\n年度匯總:")
print(summary)

本節(jié)總結(jié)

本節(jié)我們學(xué)習(xí)了 Pandas 的三種數(shù)據(jù)整合方法:

merge —— 基于列值的表關(guān)聯(lián):

  • how 參數(shù):'inner'(交集)、'left'(保留左表)、'right'(保留右表)、'outer'(并集)
  • on / left_on / right_on 指定關(guān)聯(lián)列
  • suffixes 處理重名列

join —— 基于索引的關(guān)聯(lián):

  • 默認(rèn)左連接,簡潔方便
  • 適合關(guān)聯(lián)鍵為索引的場景

concat —— 軸向拼接:

  • axis=0(默認(rèn)):上下拼接
  • axis=1:左右拼接
  • keys 添加來源標(biāo)記
  • 按索引自動對齊

到此這篇關(guān)于Pandas多源數(shù)據(jù)整合之三大數(shù)據(jù)合并方法(Merge,Join與Concat )詳解的文章就介紹到這了,更多相關(guān)Pandas數(shù)據(jù)合并內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python自動化之Ansible的安裝教程

    python自動化之Ansible的安裝教程

    這篇文章主要介紹了python自動化之Ansible的安裝方法,結(jié)合實例形式分析了自動化運維工具Ansible的安裝步驟及相關(guān)操作命令,需要的朋友可以參考下
    2019-06-06
  • Python3使用pandas模塊讀寫excel操作示例

    Python3使用pandas模塊讀寫excel操作示例

    這篇文章主要介紹了Python3使用pandas模塊讀寫excel操作,簡單講述了pandas的功能、并結(jié)合實例形式分析了Python3使用pandas模塊進(jìn)行Excel文件的讀取與寫入相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • Python實現(xiàn)的矩陣類實例

    Python實現(xiàn)的矩陣類實例

    這篇文章主要介紹了Python實現(xiàn)的矩陣類,結(jié)合完整實例形式分析了Python矩陣的定義、計算、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • python中playwright結(jié)合pytest執(zhí)行用例的實現(xiàn)

    python中playwright結(jié)合pytest執(zhí)行用例的實現(xiàn)

    本文主要介紹了python中playwright結(jié)合pytest執(zhí)行用例的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 詳解如何使用Python和正則表達(dá)式處理XML表單數(shù)據(jù)

    詳解如何使用Python和正則表達(dá)式處理XML表單數(shù)據(jù)

    在日常的Web開發(fā)中,處理表單數(shù)據(jù)是一個常見的任務(wù),而XML是一種常用的數(shù)據(jù)格式,用于在不同的系統(tǒng)之間傳遞和存儲數(shù)據(jù),本文通過闡述一個技術(shù)問題并給出解答的方式,介紹如何使用Python和正則表達(dá)式處理XML表單數(shù)據(jù),需要的朋友可以參考下
    2023-09-09
  • Fiddler如何抓取手機(jī)APP數(shù)據(jù)包

    Fiddler如何抓取手機(jī)APP數(shù)據(jù)包

    Fiddler,這個是所有軟件開發(fā)者必備神器!這款工具不僅可以抓取PC上開發(fā)web時候的數(shù)據(jù)包,而且可以抓取移動端,通過本文給大家介紹Fiddler如何抓取手機(jī)APP數(shù)據(jù)包,感興趣的朋友一起學(xué)習(xí)吧
    2016-01-01
  • Python基于多線程實現(xiàn)抓取數(shù)據(jù)存入數(shù)據(jù)庫的方法

    Python基于多線程實現(xiàn)抓取數(shù)據(jù)存入數(shù)據(jù)庫的方法

    這篇文章主要介紹了Python基于多線程實現(xiàn)抓取數(shù)據(jù)存入數(shù)據(jù)庫的方法,結(jié)合實例形式分析了Python使用數(shù)據(jù)庫類與多線程類進(jìn)行數(shù)據(jù)抓取與寫入數(shù)據(jù)庫操作的具體使用技巧,需要的朋友可以參考下
    2018-06-06
  • Python之Web框架Django項目搭建全過程

    Python之Web框架Django項目搭建全過程

    這篇文章主要介紹了Python之Web框架Django項目搭建全過程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • UI自動化定位常用實現(xiàn)方法代碼示例

    UI自動化定位常用實現(xiàn)方法代碼示例

    這篇文章主要介紹了UI自動化定位常用實現(xiàn)方法代碼示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-10-10
  • Python使用asyncio.Queue進(jìn)行任務(wù)調(diào)度的實現(xiàn)

    Python使用asyncio.Queue進(jìn)行任務(wù)調(diào)度的實現(xiàn)

    本文主要介紹了Python使用asyncio.Queue進(jìn)行任務(wù)調(diào)度的實現(xiàn),它可以用于任務(wù)調(diào)度和數(shù)據(jù)交換,文中通過示例代碼介紹的非常詳細(xì),感興趣的可以了解一下
    2024-02-02

最新評論

老河口市| 东源县| 大埔区| 稻城县| 阳朔县| 旌德县| 盘山县| 通海县| 抚顺市| 福泉市| 临澧县| 鄂托克旗| 巩留县| 宁阳县| 淄博市| 綦江县| 绥棱县| 江源县| 太保市| 红桥区| 桐梓县| 应用必备| 阿勒泰市| 永昌县| 公主岭市| 绥德县| 监利县| 蕉岭县| 共和县| 石景山区| 凤山市| 师宗县| 苗栗县| 文成县| 临桂县| 太谷县| 个旧市| 玉田县| 凤城市| 衢州市| 曲麻莱县|