Pandas: الدمج والانضمام.

آخر تحديث: 2026-08-26

البيانات الحقيقية لا تعيش أبداً في جدول واحد — معلومات المستخدم في جدول، وسجلات الطلبات في آخر، وتفاصيل المنتجات في جدول ثالث. يتطلب التحليل ربطها ببعضها، وهذا بالضبط ما تقوم به عملية الدمج (merge). تنفذ مكتبة Pandas عملية الدمج (merge) جميع أنواع الربط المستخدمة في SQL (JOIN). في هذا القسم، نستخدم مخططات Mermaid لوضوح تأثير جميع أنواع الربط الأربعة حتى تتمكن من فهم "ما يُحتفظ به من الجدول الأيسر وما يُحتفظ به من الجدول الأيمن" بشكل واضح.

⚠️ ملاحظة: يجب تشغيل الشفرة البرمجية أدناه في بيئة Python محلية.

1. What You Will Learn


2. ارتباط المستخدم بالطلب الخاص به في تجربة بوب

(١) المشكلة: جدولان منفصلان، لا توجد طريقة للتحليل

لدى بوب جدول للمستخدمين وجدول للطلبات. يريد أن يرى "ماذا اشترى كل مستخدم":

PYTHON
import pandas as pd

users = pd.DataFrame({
    'user_id': [1, 2, 3, 4],
    'name': ['Alice', 'Bob', 'Charlie', 'Carol']
})

orders = pd.DataFrame({
    'order_id': ['O001', 'O002', 'O003'],
    'user_id': [1, 2, 2],
    'amount': [120, 85, 200]
})

# How to combine? Need to link by user_id
TEXT 📖 للعرض فقط
> **الإخراج:** قم بالتشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبته مسبقاً. يرجى تثبيتها محلياً (`pip install pandas`) والمتابعة. قد تختلف القيم الفعليه قليلاً حسب إصدار pandas.

(٢) الحل: عملية الدمج في سطر واحد

▶ مثال

TEXT 📖 للعرض فقط
> **الإخراج:** قم بالتشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبته مسبقاً. يرجى تثبيتها محلياً (`pip install pandas`) والمتابعة. قد تختلف القيم الفعليه قليلاً حسب إصدار pandas.

: دمج أساسي (الصعوبة ⭐)

PYTHON
import pandas as pd

users = pd.DataFrame({
    'user_id': [1, 2, 3, 4],
    'name': ['Alice', 'Bob', 'Charlie', 'Carol']
})

orders = pd.DataFrame({
    'order_id': ['O001', 'O002', 'O003'],
    'user_id': [1, 2, 2],
    'amount': [120, 85, 200]
})

# Inner join (default) — only matching user_ids
result = pd.merge(users, orders, on='user_id')
print(result)
#    user_id     name order_id  amount
# 0        1    Alice     O001     120
# 1        2      Bob     O002      85
# 2        2      Bob     O003     200
TEXT 📖 للعرض فقط
> **الإخراج:** قم بالتشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبته مسبقاً. يرجى تثبيتها محلياً (`pip install pandas`) والمتابعة. قد تختلف القيم الفعليه قليلاً حسب إصدار pandas.

3. الأنواع الأربعة للانضمام

(1) مخطط ميرميد

100%
graph TB
    subgraph Inner["الداخلي — الاحتفاظ فقط بالتطابقات"]
        I1["user_id 1: Alice+O001"]
        I2["user_id 2: Bob+O002"]
        I3["user_id 2: Bob+O003"]
    end
    subgraph Left["اليساري — الاحتفاظ بكل الصفوف من الجدول الأيسر"]
        L1["user_id 1: Alice+O001"]
        L2["user_id 2: Bob+O002"]
        L3["user_id 2: Bob+O003"]
        L4["user_id 3: Charlie+NaN"]
        L5["user_id 4: Carol+NaN"]
    end
    subgraph Right["اليميني — الاحتفاظ بكل الصفوف من الجدول الأيمن"]
        R1["user_id 1: Alice+O001"]
        R2["user_id 2: Bob+O002"]
        R3["user_id 2: Bob+O003"]
    end
    subgraph Outer["الخارجي — الاحتفاظ بكل الصفوف من كلا الجانبين"]
        O1["user_id 1: Alice+O001"]
        O2["user_id 2: Bob+O002"]
        O3["user_id 2: Bob+O003"]
        O4["user_id 3: Charlie+NaN"]
        O5["user_id 4: Carol+NaN"]
    end
TEXT 📖 للعرض فقط
> **المخرجات:** قم بالتشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبته مسبقاً. يرجى تثبيته محلياً (`pip install pandas`) واتباع الأمثلة. قد تتغير القيم الفعلية بشكل طفيف حسب إصدار pandas.

(2) مقارنة بين الأنواع الأربعة للانضمام

النوع الكيفية جدول أيسر بدون تطابق جدول أيمن بدون تطابق عدد الصفوف
داخلي 'inner' محذوف محذوف ≤أصغر(يسار، يمين)
يساري 'left' محتفظ به (مملوء بـ NaN) محذوف = صفوف اليسار × التطابقات
يميني 'right' محذوف محتفظ به (مملوء بـ NaN) = صفوف اليمين × التطابقات
خارجي 'outer' محتفظ به (مملوء بـ NaN) محتفظ به (مملوء بـ NaN) ≥أكبر(يسار، يمين)

▶ مثال

TEXT 📖 للعرض فقط
> **المخرجات:** قم بالتشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبته مسبقاً. يرجى تثبيته محلياً (`pip install pandas`) واتباع الأمثلة. قد تتغير القيم الفعلية بشكل طفيف حسب إصدار pandas.

: مقارنة بين أنواع الانضمام الأربعة (الصعوبة ⭐⭐)

PYTHON
import pandas as pd

left = pd.DataFrame({
    'id': [1, 2, 3],
    'name': ['Alice', 'Bob', 'Charlie']
})

right = pd.DataFrame({
    'id': [2, 3, 4],
    'score': [85, 92, 78]
})

# داخلي — فقط id 2، 3 (كلا الجدولين يحتويان عليهما)
print("داخلي (INNER):")
print(pd.merge(left, right, on='id', how='inner'))
#    id    name  score
# 0   2     Bob     85
# 1   3 Charlie     92

# يساري — كل صفوف الجدول الأيسر، الجدول الأيمن يملأ NaN حيث لا يوجد تطابق
print("\nيساري (LEFT):")
print(pd.merge(left, right, on='id', how='left'))
#    id     name  score
# 0   1    Alice    NaN  ← لا يوجد تطابق في الأيمن
# 1   2      Bob   85.0
# 2   3  Charlie   92.0

# يميني — كل صفوف الجدول الأيمن
print("\nيميني (RIGHT):")
print(pd.merge(left, right, on='id', how='right'))
#    id    name  score
# 0   2     Bob     85
# 1   3 Charlie     92
# 2   4    NaN     78  ← لا يوجد تطابق في الأيسر

# خارجي — كل الصفوف من كلا الجانبين
print("\nخارجي (OUTER):")
print(pd.merge(left, right, on='id', how='outer'))
#    id     name  score
# 0   1    Alice    NaN
# 1   2      Bob   85.0
# 2   3  Charlie   92.0
# 3   4     NaN    78.0
TEXT 📖 للعرض فقط
> **المخرجات:** قم بالتشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبته مسبقاً. يرجى تثبيته محلياً (`pip install pandas`) واتباع الأمثلة. قد تتغير القيم الفعلية بشكل طفيف حسب إصدار pandas.

4. الدمج متعدد المفاتيح وأسماء الأعمدة المختلفة

(1) الدمج متعدد المفاتيح

▶ مثال

TEXT 📖 للعرض فقط
> **الإخراج:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). خادم Piston لا يحتوي على مكتبة pandas مثبتة مسبقًا. يرجى تثبيتها محليًا (`pip install pandas`) والمتابعة. قد تختلف القيم الفعلية قليلاً حسب إصدار المكتبة.

: الدمج متعدد المفاتيح (الصعوبة ⭐⭐)

PYTHON
import pandas as pd

sales = pd.DataFrame({
    'region': ['North', 'North', 'South', 'South'],
    'category': ['Electronics', 'Clothing', 'Electronics', 'Clothing'],
    'revenue': [5000, 800, 2000, 600]
})

targets = pd.DataFrame({
    'region': ['North', 'North', 'South', 'South'],
    'category': ['Electronics', 'Clothing', 'Electronics', 'Clothing'],
    'target': [4500, 1000, 2500, 500]
})

# الدمج على مفاتيح متعددة
result = pd.merge(sales, targets, on=['region', 'category'])
print(result)
#   region    category  revenue  target
# 0  North  Electronics     5000    4500
# 1  North     Clothing      800    1000
# 2  South  Electronics     2000    2500
# 3  South     Clothing      600     500

# حساب معدل الإنجاز
result['achievement'] = (result['revenue'] / result['target'] * 100).round(1)
print(result[['region', 'category', 'achievement']])
TEXT 📖 للعرض فقط
> **الإخراج:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). خادم Piston لا يحتوي على مكتبة pandas مثبتة مسبقًا. يرجى تثبيتها محليًا (`pip install pandas`) والمتابعة. قد تختلف القيم الفعلية قليلاً حسب إصدار المكتبة.

(2) الدمج عند تباين أسماء الأعمدة

▶ مثال

TEXT 📖 للعرض فقط
> **الإخراج:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). خادم Piston لا يحتوي على مكتبة pandas مثبتة مسبقًا. يرجى تثبيتها محليًا (`pip install pandas`) والمتابعة. قد تختلف القيم الفعلية قليلاً حسب إصدار المكتبة.

: left_on/right_on (الصعوبة ⭐⭐)

PYTHON
import pandas as pd

employees = pd.DataFrame({
    'emp_id': [1, 2, 3],
    'name': ['Alice', 'Bob', 'Charlie']
})

salaries = pd.DataFrame({
    'employee_id': [1, 2, 3],
    'salary': [75000, 92000, 68000]
})

# أسماء الأعمدة تختلف: emp_id مقابل employee_id
result = pd.merge(
    employees, salaries,
    left_on='emp_id', right_on='employee_id',
    how='inner'
)
print(result)
#    emp_id     name  employee_id  salary
# 0       1    Alice            1   75000
# 1       2      Bob            2   92000
# 2       3  Charlie            3   68000

# إسقاط العمود الزائد
result = result.drop(columns='employee_id')
TEXT 📖 للعرض فقط
> **الإخراج:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). خادم Piston لا يحتوي على مكتبة pandas مثبتة مسبقًا. يرجى تثبيتها محليًا (`pip install pandas`) والمتابعة. قد تختلف القيم الفعلية قليلاً حسب إصدار المكتبة.

5. اللاحقات والمُشير

(1) التعامل مع تعارضات أعمدة الأسماء

▶ مثال

TEXT 📖 للعرض فقط
> **الخرج:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبتًا مسبقًا. يرجى تثبيته محليًا (`pip install pandas`) ومتابعة الشرح. القيم الفعلية قد تختلف قليًّا حسب إصدار pandas.

: لاحقات لأسماء الأعمدة المكررة (الصعوبة ⭐)

PYTHON
import pandas as pd

df1 = pd.DataFrame({
    'id': [1, 2],
    'value': [100, 200]
})

df2 = pd.DataFrame({
    'id': [1, 2],
    'value': [300, 400]
})

# اللاحقات الافتراضية: _x و _y
result = pd.merge(df1, df2, on='id')
print(result)
#    id  value_x  value_y
# 0   1      100      300
# 1   2      200      400

# لاحقات مخصصة
result2 = pd.merge(df1, df2, on='id', suffixes=('_left', '_right'))
print(result2)
#    id  value_left  value_right
TEXT 📖 للعرض فقط
> **الخرج:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبتًا مسبقًا. يرجى تثبيته محليًا (`pip install pandas`) ومتابعة الشرح. القيم الفعلية قد تختلف قليًّا حسب إصدار pandas.

(2) مُشير لتشخيص مصادر الدمج

▶ مثال

TEXT 📖 للعرض فقط
> **الخرج:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبتًا مسبقًا. يرجى تثبيته محليًا (`pip install pandas`) ومتابعة الشرح. القيم الفعلية قد تختلف قليًّا حسب إصدار pandas.

: مُشير لتتبع أصل الصفوف (الصعوبة ⭐⭐)

PYTHON
import pandas as pd

left = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
right = pd.DataFrame({'id': [2, 3, 4], 'score': [85, 92, 78]})

# إضافة عمود _merge لمعرفة مصدر كل صف
result = pd.merge(left, right, on='id', how='outer', indicator=True)
print(result)
#    id     name  score      _merge
# 0   1    Alice    NaN   left_only
# 1   2      Bob   85.0        both
# 2   3  Charlie   92.0        both
# 3   4     NaN    78.0  right_only

# التصفية حسب مصدر الدمج
only_left = result[result['_merge'] == 'left_only']
print(f"موجود فقط في الجدول الأيسر: {len(only_left)} صفوف")  # 1 (Alice)

# التحقق من سلامة البيانات - إيجاد السجلات غير المتطابقة
unmatched = result[result['_merge'] != 'both']
print(f"السجلات غير المتطابقة: {len(unmatched)}")  # 2
TEXT 📖 للعرض فقط
> **الخرج:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبتًا مسبقًا. يرجى تثبيته محليًا (`pip install pandas`) ومتابعة الشرح. القيم الفعلية قد تختلف قليًّا حسب إصدار pandas.

6. التحقق والدمج التقاطعي

(1) التحقق من التحقق من علاقات الدمج

▶ مثال

TEXT 📖 للعرض فقط
> **المخرجات:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). لا يحتوي خادم Pandas على مكتبة pandas مثبتة مسبقاً. يرجى تثبيتها محلياً (`pip install pandas`) والمتابعة. قد تختلف القيم الفعلي قليلاً حسب إصدار pandas.

: التحقق من صحة الدمج (الصعوبة ⭐⭐)

PYTHON
import pandas as pd

users = pd.DataFrame({'user_id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
orders = pd.DataFrame({'order_id': ['O1', 'O2', 'O3'], 'user_id': [1, 2, 2]})

# التحقق: يجب أن يكون لكل مستخدم طلب واحد على الأكثر (1:1)
# سيفشل هذا لأن المستخدم 2 لديه 2 طلب
try:
    result = pd.merge(users, orders, on='user_id', validate='1:1')
except Exception as e:
    print(f"فشل التحقق: {e}")

# التحقق: يمكن للمستخدم أن يكون لديه عدة طلبات (1:m) — يمر
result = pd.merge(users, orders, on='user_id', validate='1:m')
print(result)  # مقبول

# أنواع التحقق: '1:1', '1:m', 'm:1', 'm:m'
TEXT 📖 للعرض فقط
> **المخرجات:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). لا يحتوي خادم Pandas على مكتبة pandas مثبتة مسبقاً. يرجى تثبيتها محلياً (`pip install pandas`) والمتابعة. قد تختلف القيم الفعلي قليلاً حسب إصدار pandas.

(2) الدمج التقاطعي (Cross Join)

▶ مثال

TEXT 📖 للعرض فقط
> **المخرجات:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). لا يحتوي خادم Pandas على مكتبة pandas مثبتة مسبقاً. يرجى تثبيتها محلياً (`pip install pandas`) والمتابعة. قد تختلف القيم الفعلي قليلاً حسب إصدار pandas.

: الدمج التقاطعي (الصعوبة ⭐)

PYTHON
import pandas as pd

colors = pd.DataFrame({'color': ['Red', 'Blue']})
sizes = pd.DataFrame({'size': ['S', 'M', 'L']})

# كل التوليفات (الجداء الديكارتي)
result = pd.merge(colors, sizes, how='cross')
print(result)
#   color size
# 0   Red    S
# 1   Red    M
# 2   Red    L
# 3  Blue    S
# 4  Blue    M
# 5  Blue    L
# 6 صفوف = 2 لون × 3 مقاسات
TEXT 📖 للعرض فقط
> **المخرجات:** قم بالتشغيل في بيئة بايثون محلية (pandas 2.x). لا يحتوي خادم Pandas على مكتبة pandas مثبتة مسبقاً. يرجى تثبيتها محلياً (`pip install pandas`) والمتابعة. قد تختلف القيم الفعلي قليلاً حسب إصدار pandas.

7. merge مقابل join

الميزة merge join
نمط الاستدعاء pd.merge(df1, df2) df1.join(df2)
مفتاح الربط الافتراضي العمود المحدد بواسطة on الفهرس (Index)
الربط بأعمدة متعددة ✅ on=['a','b'] ❌ الفهرس فقط
أنواع الربط inner/left/right/outer left (الافتراضي)
المرونة عالية منخفضة
الأفضل لـ الربط لأغراض عامة محاذاة الفهارس

▶ مثال

TEXT 📖 للعرض فقط
> **الإخراج:** قم بالتشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبتًا مسبقًا. يرجى تثبيته محليًا (`pip install pandas`) والعمل وفقًا لذلك. قد تتغير القيم الفعليّة بشكل طفيف اعتمادًا على إصدار pandas.

: اختصار join (الصعوبة ⭐)

PYTHON
import pandas as pd

df1 = pd.DataFrame({'A': [1, 2, 3]}, index=['x', 'y', 'z'])
df2 = pd.DataFrame({'B': [4, 5]}, index=['x', 'y'])

# join يستخدم الفهرس بشكل افتراضي
result = df1.join(df2)  # how='left' by default
print(result)
#    A    B
# x  1  4.0
# y  2  5.0
# z  3  NaN  ← left join يبقي جميع صفوف اليسار

# join مع معامل how
result2 = df1.join(df2, how='inner')
TEXT 📖 للعرض فقط
> **الإخراج:** قم بالتشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على pandas مثبتًا مسبقًا. يرجى تثبيته محليًا (`pip install pandas`) والعمل وفقًا لذلك. قد تتغير القيم الفعليّة بشكل طفيف اعتمادًا على إصدار pandas.

8. مثال كامل: تحليل الربط بين ثلاث جداول

▶ المثال

TEXT 📖 للعرض فقط
> **الخرج:** يتم التشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على مكتبة pandas مثبتة مسبقاً. يرجى تثبيتها محليًا (`pip install pandas`) والاتباع. قد تتغير القيم الفعلية قليلاً حسب إصدار pandas.

: سير عمل الدمج الثلاثي للجداول (الصعوبة ⭐⭐⭐)

PYTHON
import pandas as pd

# ============================================
# مثال شامل: دمج 3 جداول
# المستخدمون + الطلبات + المنتجات → تحليل كامل
# ============================================

# 1. جدول المستخدمين
users = pd.DataFrame({
    'user_id': [1, 2, 3, 4, 5],
    'name': ['Alice', 'Bob', 'Charlie', 'Carol', 'David'],
    'region': ['North', 'South', 'East', 'North', 'West']
})

# 2. جدول الطلبات
orders = pd.DataFrame({
    'order_id': ['O001', 'O002', 'O003', 'O004', 'O005', 'O006'],
    'user_id': [1, 2, 2, 3, 1, 5],
    'product_id': ['P01', 'P02', 'P03', 'P01', 'P04', 'P02'],
    'quantity': [2, 1, 3, 1, 5, 2]
})

# 3. جدول المنتجات
products = pd.DataFrame({
    'product_id': ['P01', 'P02', 'P03', 'P04', 'P05'],
    'product_name': ['Laptop', 'Phone', 'Tablet', 'Mouse', 'Keyboard'],
    'price': [999, 699, 349, 29, 79]
})

# الخطوة 1: الطلبات + المنتجات → تفاصيل الطلب مع السعر
order_details = pd.merge(orders, products, on='product_id', how='left')
order_details['total'] = order_details['quantity'] * order_details['price']

# الخطوة 2: تفاصيل_الطلب + المستخدمون → الصورة الكاملة
full = pd.merge(order_details, users, on='user_id', how='left')

# الخطوة 3: التحليل حسب المنطقة
region_sales = full.groupby('region')['total'].sum().sort_values(ascending=False)
print("=== المبيعات حسب المنطقة ===")
print(region_sales)

# الخطوة 4: أفضل العملاء
top_customers = full.groupby('name')['total'].sum().sort_values(ascending=False)
print("\n=== أفضل العملاء ===")
print(top_customers)

# الخطوة 5: المنتجات غير المتطابقة (في المنتجات ولكن لم تُطلب أبداً)
unmatched = pd.merge(
    products, orders[['product_id']].drop_duplicates(),
    on='product_id', how='left', indicator=True
)
never_ordered = unmatched[unmatched['_merge'] == 'left_only']
print(f"\n=== منتجات لم تُطلَب أبداً ===")
print(never_ordered[['product_id', 'product_name']])
TEXT 📖 للعرض فقط
> **الخرج:** يتم التشغيل في بيئة Python محلية (pandas 2.x). خادم Piston لا يحتوي على مكتبة pandas مثبتة مسبقاً. يرجى تثبيتها محليًا (`pip install pandas`) والاتباع. قد تتغير القيم الفعلية قليلاً حسب إصدار pandas.

❓ أسئلة شائعة

س هل يجب أن أستخدم inner أم left؟
ج الافتراضي هو inner (يحتفظ فقط بالصفوف المتطابقة، مما ينتج بيانات نظيفة). استخدم left عندما تحتاج جميع الصفوف من الجدول الأيسر (مثلاً: "جميع المستخدمين بغض النظر عن وجود طلبات لهم"). نادراً ما يُستخدم right (ما عليك سوى تبديل الجدولين واستخدام left بدلاً منه). استخدم outer لإيجاد الاختلافات ("أي المستخدمين ليس لديهم طلبات + أي الطلبات ليس لديها مستخدم"). في 80% من السيناريوهات اليومية، يكون inner هو الخيار الصحيح.
س ماذا لو كانت أسماء أعمدة المفتاح مختلفة بين الجداول؟
ج استخدم left_on و right_on لتحديد عمود المفتاح في كل جدول على حدة. مثلاً: pd.merge(a, b, left_on='emp_id', right_on='employee_id'). بعد الدجم، يحتفظ العمودان معاً — استخدم drop لإزالة العمود الزائد. إذا كان أحد المفاتيح فهرساً، استخدم left_index=True / right_index=True.
س كيف أتعامل مع تعارضات اللاحقات (suffixes)؟
ج عندما يكون في كلا الجدولين عمود بنفس الاسم (باستثناء المفتاح)، يُلحق الدمج تلقائياً اللاحقات _x و _y. استخدم suffixes=('_left','_right') لتخصيصها. أفضل ممارسة هي إعادة تسمية الأعمدة قبل الدمج لتجنب الالتباس: df.rename(columns={'value': 'value_a'}).
س ما الفرق بين merge و join؟
ج merge أكثر تنوعاً — يدعم الدمج القائم على الأعمدة، والدمج بمفاتيح متعددة، وجميع أنواع الدمج الأربعة. join أكثر إيجازاً — يندمج على الفهرس بشكل افتراضي و يستخدم left join كنمط افتراضي. استخدم merge عندما تحتاج دمجاً بأعمدة متعددة؛ استخدم join للمحاذاة البسيطة على الفهرس. بشكل عام، فضّل merge لشموله وتعامل مع join كاختصار.
س كيف أتحقق من صحة نتيجة الدمج؟
ج فحص ثلاثي الخطوات: ① قارن عدد الصفوف قبل وبعد الدمج (يجب أن يكون inner ≤ الحد الأدنى، left يجب أن يساوي عدد صفوف الجدول الأيسر × المطابقات)؛ ② استخدم indicator=True لفحص أصل كل صف (both/left_only/right_only)؛ ③ استخدم validate='1:1' أو '1:m' للتأكد من العلاقة المتوقعة — يثير خطأاً إذا تم انتهاكها.
س ماذا لو أدى الدمج إلى انفجار في عدد الصفوف؟
ج يشير انفجار الصفوف إلى دمج m:m (متعدد إلى متعدد) — عندما يتطابق كل مفتاح في الجدول الأيمن مع N صفوف، يكون الناتج = عدد صفوف الجدول الأيسر × N. الحل: قم بإزالة التكرارات أو التجميع (groupby + agg) للجدول الأيمن قبل الدمج لتقليل الصفوف المتطابقة. استخدم validate='m:1' للكشف المبكر عن ذلك.
س متى يجب استخدام cross join؟
ج يقوم cross join بإنتاج جداء كارتيزي (كل صف × كل صف)، مع عدد صفوف = عدد صفوف الجدول الأيسر × عدد صفوف الجدول الأيمن. استخدمه فقط لإنشاء تركيبات (مثلاً: الألوان × الأحجام = جميع متغيرات SKU). لا تستخدم cross join أبداً على جداول كبيرة — 1000 × 1000 = مليون صف!

📖 ملخص


📝 تمارين

  1. أساسي (صعوبة ⭐): أنشئ جدولًا للطلاب وجدولًا للدرجات (يشاركان student_id). قم بعمليات الدمج الداخلية/اليسرى/الخارجية ولاحظ كيف يتغير عدد الصفوف.
  2. متوسط (صعوبة ⭐⭐): أنشئ جدول الأقسام (dept_id/dept_name) وجدول الموظفين (emp_id/dept_id/salary). ادمجهما، واحسب متوسط الراتب لكل قسم، واستخدم المؤشر لإيجاد الأقسام التي ليس لديها موظفون.
  3. تحدي (صعوبة ⭐⭐⭐): قم بمحاكاة ثلاث جداول (users/orders/products) وأكمل ما يلي: الدمج الداخلي لدمجها → حساب إجمالي الإنفاق لكل مستخدم → الدمج اليسري لإيجاد المستخدمين الذين انفاقهم صفر → validate للتحقق من العلاقات → indicator لتشخيص المصادر.

← Previous: GroupBy and Aggregation · Next: Concat and Append →

Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%