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

การเชื่อมด้านซ้ายและด้านขวา

ดำเนินการเชื่อมด้านซ้ายและด้านขวาเพื่อเก็บแถวทั้งหมดจากตารางหนึ่ง พร้อมจับคู่ระเบียนจากอีกตาราง

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

Join แบบไม่สมมาตร

Inner และ outer join ปฏิบัติต่อ DataFrame ทั้งสองชุดอย่างสมมาตร แต่บ่อยครั้งคุณต้องการคงระเบียนทั้งหมดจากตารางหนึ่งไว้ แล้วเพิ่มข้อมูลจากอีกตารางหนึ่งให้กับระเบียนเหล่านั้น นี่คือกรณีที่ left join และ right join มีประโยชน์ join แบบไม่สมมาตรเหล่านี้พบได้บ่อยมากในการวิเคราะห์ข้อมูล เช่น เก็บธุรกรรมทั้งหมดไว้ แล้วเพิ่มชื่อสินค้าเมื่อมีข้อมูล หรือเก็บผู้ใช้ทั้งหมดไว้ แล้วเพิ่มวันที่ซื้อครั้งล่าสุดหากมีข้อมูล

Left Join: คงแถวทั้งหมดฝั่งซ้าย

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

import pandas as pd

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

result = pd.merge(orders, customers, on='customer_id', how='left')
print(result)
# All 4 orders kept; order with customer_id=999 gets NaN for name

โครงสร้างผลลัพธ์ของ Left Join

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

result = pd.merge(orders, customers, on='customer_id', how='left')
print(result)
#    order_id  customer_id  amount   name
# 0         1          101     250  Alice
# 1         2          102      80    Bob
# 2         3          101     320  Alice
# 3         4          999     150    NaN  <- no matching customer

# Count unmatched
unmatched = result['name'].isna().sum()
print(f'{unmatched} orders have no customer record')

ควรใช้ Left Join เมื่อใด

left join เหมาะเมื่อDataFrame ฝั่งซ้ายเป็นตารางหลัก และตารางฝั่งขวาเป็นข้อมูลเสริม ตัวอย่างสถานการณ์ที่พบบ่อย ได้แก่ การเพิ่มข้อมูลจากตารางมิติให้กับตารางข้อเท็จจริง (คำสั่งซื้อ + ชื่อสินค้า) การเพิ่มข้อมูลกำกับที่อาจมีหรือไม่มีก็ได้ (ผู้ใช้ + ข้อมูลโปรไฟล์) หรือการคำนวณตัวชี้วัดให้กับทุกระเบียน แม้การค้นหาข้อมูลจะไม่สำเร็จ ในโค้ดวิเคราะห์ข้อมูลส่วนใหญ่ left join พบได้บ่อยกว่า right join มาก

# Realistic pattern: enrich all products with optional category data
products = pd.DataFrame({'sku': ['A1', 'B2', 'C3'], 'price': [10, 20, 15]})
categories = pd.DataFrame({'sku': ['A1', 'C3'], 'category': ['Tools', 'Home']})

# Keep all products; add category where available
enriched = pd.merge(products, categories, on='sku', how='left')
print(enriched)
#    sku  price category
# 0   A1     10    Tools
# 1   B2     20      NaN
# 2   C3     15     Home

Right Join: คงแถวทั้งหมดฝั่งขวา

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

# Right join: keep all customers, attach orders where they exist
result = pd.merge(orders, customers, on='customer_id', how='right')
print(result)
# All 3 customers appear; Carol (103) has NaN for order_id and amount

# Equivalent left join (swap arguments):
result2 = pd.merge(customers, orders, on='customer_id', how='left')
# Same data, just column order differs

เปรียบเทียบ Join ทั้งสี่ประเภท

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

# Summary table
# how='inner'  : rows in BOTH tables
# how='left'   : ALL left rows  + matched right
# how='right'  : matched left   + ALL right rows
# how='outer'  : ALL left rows  + ALL right rows

# Test each
for how in ['inner', 'left', 'right', 'outer']:
    r = pd.merge(orders, customers, on='customer_id', how=how)
    print(f'{how}: {len(r)} rows')

การเติมค่า NaN ในผลลัพธ์ของ Left Join

หลังจากทำ left join แถวที่ไม่ตรงกันจะมีค่า NaN ในคอลัมน์ของตารางฝั่งขวา โดยทั่วไปคุณอาจต้องการเติมค่าเริ่มต้นที่เหมาะสมลงไป เช่น 'Unknown' สำหรับหมวดหมู่ที่ขาดหาย หรือ 0 สำหรับจำนวนที่ขาดหาย ให้ใช้ fillna() กับผลลัพธ์ หรือส่ง fill_value ในการดำเนินการทางคณิตศาสตร์ที่ทำต่อจาก join

result = pd.merge(products, categories, on='sku', how='left')
result['category'] = result['category'].fillna('Uncategorised')
print(result)
#    sku  price       category
# 0   A1     10          Tools
# 1   B2     20  Uncategorised
# 2   C3     15           Home

Left Anti-Join: แถวที่ไม่มีรายการตรงกัน

รูปแบบที่มีประโยชน์และไม่ได้รองรับโดยตรงผ่าน how คือ anti-join ซึ่งจะเก็บเฉพาะแถวฝั่งซ้ายที่ไม่มีรายการตรงกันในตารางฝั่งขวา ให้ดำเนินการโดยใช้ left join พร้อม indicator=True จากนั้นกรองค่า _merge == 'left_only' วิธีนี้เหมาะอย่างยิ่งสำหรับค้นหาระเบียนที่ไม่มีข้อมูลคู่ รายการใหม่ที่ไม่มีอยู่ในรายการอ้างอิง หรือธุรกรรมที่หายไปจากบัญชีแยกประเภท

# Anti-join: orders with no matching customer record
result = pd.merge(orders, customers, on='customer_id',
                  how='left', indicator=True)
unmatched_orders = result[result['_merge'] == 'left_only'].drop(columns='_merge')
print(unmatched_orders)
#    order_id  customer_id  amount  name
# 3         4          999     150   NaN

การคงจำนวนแถวด้วย Left Join

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

# Right table has duplicate keys -> row multiplication
orders_small = pd.DataFrame({'id': [1, 2], 'amount': [100, 200]})
multi_customer = pd.DataFrame({
    'id': [1, 1],  # duplicate!
    'contact': ['Alice', 'Alice2']
})

result = pd.merge(orders_small, multi_customer, on='id', how='left')
print(len(result))  # 3 rows! order 1 appears twice
print(result)

รูปแบบการใช้ Left Join ในโลกจริง

ตัวอย่างลำดับการทำงานที่ใช้ได้จริงมีดังนี้ เริ่มจากบันทึกธุรกรรม ทำ left join กับแค็ตตาล็อกสินค้าเพื่อดึงชื่อสินค้า จากนั้นทำ left join กับตารางลูกค้าเพื่อดึงชื่อลูกค้า เติมค่าเริ่มต้นให้กับข้อมูลที่ค้นหาไม่พบ การทำ left join ต่อเนื่องกันช่วยให้คงแถวธุรกรรมทุกแถวไว้ได้ แม้จะไม่มีระเบียนสินค้าหรือลูกค้าในตารางอ้างอิง

transactions = pd.DataFrame({
    'txn_id': [1, 2, 3],
    'cust_id': [10, 11, 99],
    'prod_id': [20, 21, 20],
    'total': [50, 30, 70]
})

custs = pd.DataFrame({'cust_id': [10, 11], 'cust_name': ['Alice', 'Bob']})
prods = pd.DataFrame({'prod_id': [20, 21], 'prod_name': ['Widget', 'Gadget']})

result = (
    transactions
    .merge(custs, on='cust_id', how='left')
    .merge(prods, on='prod_id', how='left')
)
print(result)

การตัดสินใจเลือกระหว่าง Left Join กับ Inner Join

การเลือกระหว่าง left และ inner join เป็นการตัดสินใจด้านตรรกะทางธุรกิจ กล่าวคือ ควรเก็บระเบียนที่ไม่พบรายการอ้างอิงไว้ หรือควรลบออกโดยไม่มีการแจ้งเตือน ให้ใช้ left join เมื่อการค้นหาข้อมูลอ้างอิงไม่พบเป็นสิ่งที่ยอมรับได้และคุณต้องการเก็บระเบียนหลักทั้งหมดไว้ ให้ใช้ inner join เมื่อการค้นหาข้อมูลอ้างอิงไม่พบหมายความว่าระเบียนนั้นไม่ถูกต้องและควรตัดออกจากการวิเคราะห์ โปรดบันทึกไว้เสมอว่าคุณเลือกวิธีใดและเพราะเหตุใด

# Left join: keep all transactions (some may have no product name)
result_left = pd.merge(transactions, prods, on='prod_id', how='left')
print('Left join rows:', len(result_left))   # same as transactions

# Inner join: only transactions with known product
result_inner = pd.merge(transactions, prods, on='prod_id', how='inner')
print('Inner join rows:', len(result_inner))  # may be fewer

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

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

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

ในบทเรียนนี้ คุณได้เรียนรู้ว่า left join จะคงทุกแถวจาก DataFrame ฝั่งซ้ายไว้ และเติม NaN ให้กับคอลัมน์ฝั่งขวาสำหรับแถวที่ไม่ตรงกัน right join เป็นภาพสะท้อนของวิธีดังกล่าว รูปแบบ anti-join ที่ใช้ indicator=True จะค้นหาแถวฝั่งซ้ายที่ไม่มีรายการตรงกันทางฝั่งขวา และการเลือกระหว่าง left กับ inner join เป็นการตัดสินใจด้านตรรกะทางธุรกิจ ต่อไปเราจะสำรวจการ join DataFrame ด้วยดัชนีแทนการใช้คอลัมน์

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

บทเรียน “การเชื่อมด้านซ้ายและด้านขวา” ฟรีหรือไม่

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

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

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

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

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

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

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

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

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

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

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