0Pricing
Pandas & NumPy Academy · บทเรียน

pd.merge: การเชื่อมแบบด้านในและด้านนอก

รวม DataFrames สองชุดตามคอลัมน์คีย์ร่วมด้วยการเชื่อมแบบด้านในและด้านนอก และทำความเข้าใจว่าแถวใดจะถูกเก็บหรือลบ

pd.merge: การเชื่อมแบบด้านในและด้านนอก เป็นบทเรียน Pandas & NumPy Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Pandas & NumPy Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน

join คืออะไร

join ใช้รวม DataFrame สองชุดเข้าด้วยกัน โดยจับคู่แถวตามคอลัมน์คีย์ที่มีร่วมกัน ซึ่งเป็นแนวคิดเดียวกับคำสั่ง JOIN ของ SQL Pandas ใช้ pd.merge() เพื่อดำเนินการ join ต่างจาก pd.concat() ที่เพียงนำข้อมูลมาต่อกัน pd.merge() จะจัดแนวแถวจากตารางสองชุดที่แตกต่างกันอย่างชาญฉลาด โดยอาศัยค่าที่ตรงกันในคอลัมน์อย่างน้อยหนึ่งคอลัมน์

คอลัมน์คีย์ร่วมกัน

การ merge จะทำงานได้ DataFrame ทั้งสองชุดต้องมีคอลัมน์อย่างน้อยหนึ่งคอลัมน์ที่มีค่าร่วมกัน ซึ่งเรียกว่า คอลัมน์คีย์ ตัวอย่างเช่น ตาราง orders มีคอลัมน์ customer_id และตาราง customers ก็มีคอลัมน์ customer_id เช่นกัน การ merge ด้วย customer_id จะเพิ่มรายละเอียดลูกค้าให้กับแถวคำสั่งซื้อแต่ละแถว ให้ระบุคีย์ด้วยพารามิเตอร์ on เมื่อ DataFrame ทั้งสองชุดใช้ชื่อคอลัมน์เดียวกัน

import pandas as pd

orders = pd.DataFrame({
    'order_id': [1, 2, 3, 4],
    'customer_id': [101, 102, 101, 103],
    'amount': [250, 80, 320, 150]
})

customers = pd.DataFrame({
    'customer_id': [101, 102, 104],
    'name': ['Alice', 'Bob', 'Diana']
})

Inner Join: จุดร่วมของตารางทั้งสอง

inner join (ค่าเริ่มต้น) จะเก็บเฉพาะแถวที่ค่าคีย์มีอยู่ใน DataFrame ทั้งสองชุด แถวในตารางใดก็ตามที่ไม่มีคีย์ตรงกันในอีกตารางจะถูกลบออกโดยไม่มีการแจ้งเตือน ในตัวอย่างคำสั่งซื้อ ลูกค้า 103 และ 104 ไม่มีรายการตรงกันในอีกตาราง ดังนั้นแถวของลูกค้าเหล่านี้จึงไม่อยู่ในผลลัพธ์ของ inner join

# Inner join (default): only matching rows from both
result = pd.merge(orders, customers, on='customer_id', how='inner')
print(result)
#    order_id  customer_id  amount   name
# 0         1          101     250  Alice
# 1         3          101     320  Alice
# 2         2          102      80    Bob
# Order 4 (customer 103) dropped - no match in customers
# Diana (customer 104) dropped - no match in orders

Outer Join: การรวมข้อมูลจากตารางทั้งสอง

outer join (how='outer') จะเก็บทุกแถวจาก DataFrame ทั้งสองชุด หากแถวใดไม่มีคีย์ที่ตรงกันในอีกตาราง คอลัมน์ที่ขาดหายไปจะถูกเติมด้วย NaN วิธีนี้มีประโยชน์เมื่อต้องการเห็นภาพข้อมูลทั้งสองชุดอย่างครบถ้วน โดยยังคงเก็บระเบียนที่จับคู่ไม่สำเร็จไว้

result = pd.merge(orders, customers, on='customer_id', how='outer')
print(result)
#    order_id  customer_id  amount   name
# 0       1.0          101   250.0  Alice
# 1       3.0          101   320.0  Alice
# 2       2.0          102    80.0    Bob
# 3       4.0          103   150.0    NaN  <- order with unknown customer
# 4       NaN          104     NaN  Diana  <- customer with no orders

การ Merge คอลัมน์ที่มีชื่อต่างกัน

เมื่อคอลัมน์คีย์มีชื่อต่างกันใน DataFrame แต่ละชุด ให้ใช้ left_on และ right_on แทน on Pandas จะจับคู่แถวที่ค่า left_on ใน DataFrame ฝั่งซ้ายเท่ากับค่า right_on ใน DataFrame ฝั่งขวา คอลัมน์คีย์ทั้งสองจะปรากฏในผลลัพธ์ และคุณสามารถใช้ drop เพื่อลบคอลัมน์ที่ซ้ำซ้อนออกภายหลังได้

products = pd.DataFrame({
    'prod_id': [10, 20, 30],
    'name': ['Widget', 'Gadget', 'Doohickey']
})

order_lines = pd.DataFrame({
    'item_id': [10, 10, 20],
    'qty': [3, 1, 5]
})

result = pd.merge(order_lines, products,
                  left_on='item_id', right_on='prod_id')
print(result.drop(columns='prod_id'))
#    item_id  qty    name
# 0       10    3  Widget
# 1       10    1  Widget
# 2       20    5  Gadget

การ Merge ด้วยหลายคอลัมน์

หากต้องการจับคู่แถวด้วยชุดผสมของคอลัมน์ (คีย์ผสม) ให้ส่งรายการไปยัง on วิธีนี้พบได้บ่อยเมื่อคอลัมน์เดียวไม่เพียงพอที่จะจับคู่ให้ไม่ซ้ำกัน เช่น การ merge ด้วยทั้ง year และ region คอลัมน์ทั้งหมดที่ระบุจะต้องตรงกันพร้อมกัน แถวนั้นจึงจะถูกรวมไว้ในผลลัพธ์

targets = pd.DataFrame({
    'year': [2023, 2023, 2024],
    'region': ['East', 'West', 'East'],
    'target': [100, 150, 120]
})
actuals = pd.DataFrame({
    'year': [2023, 2024, 2024],
    'region': ['East', 'East', 'West'],
    'actual': [95, 115, 80]
})

result = pd.merge(targets, actuals, on=['year', 'region'], how='inner')
print(result)
#    year region  target  actual
# 0  2023   East     100      95
# 1  2024   East     120     115

การจัดการชื่อคอลัมน์ที่ซ้ำกัน

เมื่อ DataFrame ทั้งสองชุดมีคอลัมน์ชื่อเดียวกัน (นอกเหนือจากคีย์) Pandas จะเติมส่วนต่อท้ายเพื่อแยกความแตกต่าง โดยค่าเริ่มต้นคือ _x สำหรับฝั่งซ้าย และ _y สำหรับฝั่งขวา คุณสามารถกำหนดค่าเหล่านี้เองด้วยพารามิเตอร์ suffixes เพื่อให้ได้ชื่อที่สื่อความหมายมากขึ้นและลดความสับสนในผลลัพธ์

df_a = pd.DataFrame({'id': [1, 2], 'value': [10, 20]})
df_b = pd.DataFrame({'id': [1, 2], 'value': [100, 200]})

# Default suffixes
print(pd.merge(df_a, df_b, on='id'))
#    id  value_x  value_y

# Custom suffixes
print(pd.merge(df_a, df_b, on='id', suffixes=('_budget', '_actual')))
#    id  value_budget  value_actual

การตรวจสอบข้อมูลซ้ำที่ไม่คาดคิด

ปัญหาที่พบบ่อยในการ merge คือจำนวนแถวเพิ่มขึ้นโดยไม่คาดคิด หากคอลัมน์คีย์มีค่าซ้ำกันใน DataFrame ทั้งสองชุด การ merge จะสร้างผลคูณคาร์ทีเซียนของแถวที่ตรงกันทั้งหมด โปรดตรวจสอบจำนวนแถวหลังการ merge เสมอ หากจำนวนมากกว่าที่คาดไว้ ให้ตรวจสอบค่าซ้ำในคอลัมน์คีย์ด้วย df.duplicated(subset=['key']).sum()

# Both tables have duplicate keys -> cartesian product
left = pd.DataFrame({'id': [1, 1], 'val_l': ['a', 'b']})
right = pd.DataFrame({'id': [1, 1], 'val_r': ['x', 'y']})

result = pd.merge(left, right, on='id')
print(len(result))  # 4 rows! (2x2 cartesian product)
print(result)
#    id val_l val_r
# 0   1     a     x
# 1   1     a     y
# 2   1     b     x
# 3   1     b     y

พารามิเตอร์ validate เพื่อความปลอดภัย

ส่งพารามิเตอร์ validate เพื่อบังคับใช้ข้อกำหนดความสัมพันธ์ในการ merge และทำให้เกิดข้อผิดพลาดหากมีการละเมิดข้อกำหนด 'one_to_one' กำหนดให้คีย์ในตารางทั้งสองไม่ซ้ำกัน 'one_to_many' กำหนดให้คีย์ในตารางฝั่งซ้ายไม่ซ้ำกัน และ 'many_to_one' กำหนดเฉพาะคีย์ในตารางฝั่งขวา วิธีนี้เป็นแนวทางการเขียนโค้ดเชิงป้องกันที่ดีเยี่ยม เพราะช่วยตรวจพบปัญหาคุณภาพข้อมูลได้ตั้งแต่เนิ่น ๆ

# Safe merge: validate that customer_id is unique in customers
try:
    result = pd.merge(orders, customers,
                      on='customer_id',
                      how='inner',
                      validate='many_to_one')
    print('Merge OK, shape:', result.shape)
except Exception as e:
    print('Merge error:', e)

การตรวจสอบความครอบคลุมด้วย indicator

ส่ง indicator=True เพื่อเพิ่มคอลัมน์ _merge ให้กับผลลัพธ์ โดยคอลัมน์นี้จะแสดงว่าแต่ละแถวมาจากที่ใด: 'left_only', 'right_only' หรือ 'both' วิธีนี้มีประโยชน์หลังทำ outer join เพื่อระบุว่าระเบียนใดจับคู่ได้และระเบียนใดจับคู่ไม่ได้ ช่วยให้คุณตรวจสอบคุณภาพข้อมูลก่อนลบคอลัมน์ตัวบ่งชี้ออก

result = pd.merge(orders, customers, on='customer_id',
                  how='outer', indicator=True)
print(result['_merge'].value_counts())
# both           3
# left_only      1  <- orders with no customer record
# right_only     1  <- customers with no orders

# Find unmatched orders
print(result[result['_merge'] == 'left_only'])

สรุป Inner กับ Outer

สรุปประเภท join ทั้งสองแบบ: inner join ให้จุดร่วม ซึ่งมีเฉพาะแถวที่มีคีย์ตรงกันใน DataFrame ทั้งสองชุด ส่วน outer join ให้การรวม ซึ่งมีทุกแถวจาก DataFrame ทั้งสองชุด และเติม NaN เมื่อไม่มีรายการตรงกัน เพื่อให้ครบถ้วน: left join จะคงทุกแถวจาก DataFrame ฝั่งซ้าย และ right join จะคงทุกแถวจาก DataFrame ฝั่งขวา โดยจะกล่าวถึงหัวข้อเหล่านี้ในบทเรียนถัดไป

# Quick reference
# how='inner'  -> intersection: only matched rows
# how='outer'  -> union: all rows from both, NaN for no match
# how='left'   -> all left rows + matched right rows
# how='right'  -> all right rows + matched left rows

# Most common: inner (default) for enrichment, left for preserving records

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจของคุณเกี่ยวกับ inner และ outer join ของ pd.merge จากบทเรียนนี้

ทบทวนบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า pd.merge() ที่ใช้ how='inner' จะเก็บเฉพาะแถวที่ตรงกันจาก DataFrame ทั้งสองชุด ขณะที่ how='outer' จะเก็บทุกแถวและใช้ NaN สำหรับแถวที่ไม่ตรงกัน on ใช้ระบุคีย์ร่วมกัน ส่วน left_on/right_on ใช้จัดการชื่อคอลัมน์ที่แตกต่างกัน และพารามิเตอร์ indicator ช่วยตรวจสอบว่าแถวใดจับคู่กันได้ ต่อไปเราจะสำรวจ left และ right join เพื่อคงทุกแถวจากฝั่งใดฝั่งหนึ่ง

คำถามที่พบบ่อย

บทเรียน “pd.merge: การเชื่อมแบบด้านในและด้านนอก” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “pd.merge: การเชื่อมแบบด้านในและด้านนอก” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Pandas & NumPy Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Pandas & NumPy Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “pd.merge: การเชื่อมแบบด้านในและด้านนอก”

รวม DataFrames สองชุดตามคอลัมน์คีย์ร่วมด้วยการเชื่อมแบบด้านในและด้านนอก และทำความเข้าใจว่าแถวใดจะถูกเก็บหรือลบ คุณปฏิบัติ Pandas & NumPy Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Pandas & NumPy Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Pandas & NumPy Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “pd.merge: การเชื่อมแบบด้านในและด้านนอก” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Pandas & NumPy Academy นี้ได้ไหม

ได้ บทเรียน Pandas & NumPy Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. pd.concat สำหรับการซ้อน DataFrames
  2. pd.merge: การเชื่อมแบบด้านในและด้านนอก
  3. การเชื่อมด้านซ้ายและด้านขวา
  4. การเชื่อมตามดัชนี
← กลับไปที่ Pandas & NumPy Academy