Pandas & NumPy Academy · درس

عمليات الربط اليسرى واليمنى

نفّذ عمليات ربط يسرى ويمنى للحفاظ على جميع الصفوف من أحد الجدولين، مع مطابقة السجلات من الجدول الآخر.

الدرس 3 من 413 خطوة

عمليات الربط اليسرى واليمنى درس مجاني في Pandas & NumPy Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Pandas & NumPy Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.

عمليات الربط غير المتماثلة

يتعامل الربطان الداخلي والخارجي مع كلا DataFrame بشكل متماثل. لكنكم قد ترغبون غالبًا في الحفاظ على جميع السجلات من جدول واحد مع إثرائها ببيانات من جدول آخر. وهنا يأتي دور الربطين الأيسر والأيمن. تُستخدم عمليات الربط غير المتماثلة هذه بكثرة في التحليلات: الاحتفاظ بجميع المعاملات وإضافة أسماء المنتجات عند توفرها، أو الاحتفاظ بجميع المستخدمين وإضافة تاريخ آخر عملية شراء لهم إن وُجد.

الربط الأيسر: الحفاظ على جميع الصفوف اليسرى

يحتفظ الربط الأيسر (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

بنية نتيجة الربط الأيسر

بعد إجراء ربط أيسر، ستحتوي الصفوف من DataFrame الأيسر التي لم تجد تطابقًا في 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')

متى يُستخدم الربط الأيسر

يكون الربط الأيسر مناسبًا عندما يكون DataFrame الأيسر هو الجدول الأساسي ويكون الجدول الأيمن تكميليًا. ومن السيناريوهات الشائعة: إثراء جدول وقائع بجدول أبعاد (الطلبات + أسماء المنتجات)، أو إضافة بيانات وصفية اختيارية (المستخدمون + بيانات الملف الشخصي)، أو حساب المقاييس لجميع السجلات حتى عند فشل البحث عن قيمة. وفي معظم شيفرات التحليلات، تكون عمليات الربط الأيسر أكثر شيوعًا بكثير من الربط الأيمن.

# 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

الربط الأيمن: الحفاظ على جميع الصفوف اليمنى

يُعد الربط الأيمن (how='right') الصورة المعاكسة للربط الأيسر: إذ يحتفظ بكل صف من DataFrame الأيمن، ويملأ أعمدة الجدول الأيسر بالقيمة NaN عند عدم وجود تطابق. ويُستخدم الربط الأيمن بدرجة أقل، إذ يمكنكم دائمًا الحصول على النتيجة نفسها بتبديل معاملي DataFrame واستخدام ربط أيسر بدلًا منه، وهو أوضح للقراء.

# 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

مقارنة أنواع الربط الأربعة

تختلف أنواع الربط الأربعة فقط في الصفوف التي تحتفظ بها من الجانب غير المتطابق. 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 في نتائج الربط الأيسر

بعد إجراء ربط أيسر، تحتوي الصفوف غير المتطابقة على NaN في أعمدة الجدول الأيمن. وغالبًا ما ترغبون في ملء هذه القيم بقيم افتراضية منطقية — مثل 'Unknown' لفئة مفقودة أو 0 لعدد مفقود. استخدموا fillna() على النتيجة، أو مرّروا fill_value في العمليات الحسابية التي تلي عملية الربط.

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

الربط المضاد الأيسر: الصفوف غير المتطابقة

من الأنماط المفيدة التي لا يدعمها how مباشرةً الربط المضاد: الاحتفاظ فقط بالصفوف اليسرى التي لا تملك أي تطابق في الجدول الأيمن. طبّقوه باستخدام ربط أيسر مع 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

الحفاظ على عدد الصفوف باستخدام الربط الأيسر

عندما يملك DataFrame الأيمن مفاتيح فريدة، يضمن الربط الأيسر الحفاظ على عدد الصفوف نفسه تمامًا الموجود في الجدول الأيسر. ولكن إذا احتوى الجدول الأيمن على قيم مفاتيح مكررة، فسيضاعف الربط الأيسر الصفوف، تمامًا كما يفعل الربط الداخلي. تحقّقوا دائمًا من أن عدد صفوف الناتج يطابق عدد صفوف الجدول الأيسر عندما تتوقعون علاقة واحد إلى متعدد.

# 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)

نمط الربط الأيسر في العالم الحقيقي

إليكم سير عمل كامل من العالم الحقيقي: ابدأوا بسجل للمعاملات، ثم أجروا ربطًا أيسر مع كتالوج المنتجات للحصول على الأسماء، وبعد ذلك ربطًا أيسر مع جدول العملاء للحصول على الأسماء. املؤوا عمليات البحث المفقودة بقيم افتراضية. تضمن سلسلة الربط الأيسر الحفاظ على كل صف من صفوف المعاملات حتى عند فقدان سجل المنتج أو العميل من الجداول المرجعية.

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: 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

تحقق سريع

اختبروا مدى فهمكم للربطين الأيسر والأيمن مما ورد في هذا الدرس.

مراجعة الدرس

في هذا الدرس تعلّمتم أن الربط الأيسر يحافظ على جميع الصفوف من DataFrame الأيسر، ويملأ الأعمدة اليمنى بالقيمة NaN عند عدم وجود تطابق؛ وأن الربط الأيمن هو الصورة المعاكسة؛ وأن نمط الربط المضاد باستخدام indicator=True يعثر على الصفوف اليسرى التي لا تملك تطابقًا يمينًا؛ وأن الاختيار بين الربط الأيسر والداخلي هو قرار متعلق بمنطق الأعمال. بعد ذلك، سنستكشف ربط DataFrames باستخدام الفهرس بدلًا من العمود.

البدء مجانًا

تعلم Python مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
30
الدروس
120

الأسئلة الشائعة

هل درس «عمليات الربط اليسرى واليمنى» مجاني؟

نعم — نص درس «عمليات الربط اليسرى واليمنى» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Pandas & NumPy Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.

ماذا ستتعلم في «عمليات الربط اليسرى واليمنى»؟

نفّذ عمليات ربط يسرى ويمنى للحفاظ على جميع الصفوف من أحد الجدولين، مع مطابقة السجلات من الجدول الآخر. تتمرن على Pandas & NumPy Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Pandas & NumPy Academy؟

لا تُشترط خبرة سابقة. Pandas & NumPy Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «عمليات الربط اليسرى واليمنى»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Pandas & NumPy Academy هذا؟

نعم. كل درس في Pandas & NumPy Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. ‏pd.concat لتكديس DataFrame
  2. ‏pd.merge: عمليات الربط الداخلي والخارجي
  3. عمليات الربط اليسرى واليمنى
  4. الربط حسب الفهرس
← العودة إلى Pandas & NumPy Academy