دمج وتوحيد الجداول (Merge, Join, Concat) لبناء قاعدة بيانات تحليلية شاملة


مرحباً بكم أيها المبرمجون! اليوم سنبني معاً أساساً قوياً لقاعدة بيانات تحليلية شاملة من خلال تعلم كيفية دمج وتوحيد الجداول باستخدام مكتبة Pandas في Python.

سنتعلم كيفية ربط مصادر بيانات متعددة أفقياً (Merge, Join) وعمودياً (Concat) لإنشاء مجموعة بيانات متكاملة وجاهزة للتحليل العميق.

1. التحضير للبيانات الأولية

لنبني قاعدة بيانات تحليلية، نحتاج أولاً إلى بيانات. سنقوم بإنشاء ثلاثة جداول (DataFrames) تمثل المبيعات، المنتجات، والعملاء، وهي سيناريوهات شائعة في قواعد البيانات التجارية.

ملاحظة تقنية: DataFrames هي هياكل بيانات ثنائية الأبعاد في Pandas تشبه الجداول في قواعد البيانات العلائقية.
import pandas as pd

# DataFrame للمبيعات
df_sales = pd.DataFrame({
    'sale_id': [1, 2, 3, 4, 5, 6],
    'product_id': [101, 102, 101, 103, 102, 101],
    'customer_id': [1, 2, 1, 3, 2, 4],
    'quantity': [2, 1, 3, 1, 2, 1],
    'price': [10.0, 25.0, 10.0, 50.0, 25.0, 10.0]
})
# DataFrame للمنتجات
df_products = pd.DataFrame({
    'product_id': [101, 102, 103, 104],
    'product_name': ['Laptop', 'Mouse', 'Keyboard', 'Monitor'],
    'category': ['Electronics', 'Electronics', 'Electronics', 'Electronics']
})
# DataFrame للعملاء
df_customers = pd.DataFrame({
    'customer_id': [1, 2, 3, 4, 5],
    'customer_name': ['Ahmed', 'Sara', 'Khalid', 'Laila', 'Nour'],
    'city': ['Riyadh', 'Jeddah', 'Dammam', 'Riyadh', 'Jeddah']
})

print("بيانات المبيعات الأولية:")
print(df_sales)
print("\nبيانات المنتجات الأولية:")
print(df_products)
print("\nبيانات العملاء الأولية:")
print(df_customers)

2. دمج البيانات أفقياً باستخدام Merge (Join)

الآن بعد أن أصبح لدينا جداول منفصلة، سنقوم بدمجها أفقياً لإنشاء جدول مبيعات غني بالمعلومات حول المنتجات والعملاء. سنستخدم دالة pd.merge().

ملاحظة تقنية: pd.merge() تعادل عمليات JOIN في SQL. الأنواع الشائعة هي 'inner' (التقاطع), 'left' (كل شيء من اليسار والمطابقات من اليمين), 'right' (كل شيء من اليمين والمطابقات من اليسار), و 'outer' (الاتحاد).
# دمج المبيعات مع المنتجات باستخدام 'product_id'
# سنستخدم 'inner' join لضمان وجود المنتج في كلا الجدولين
merged_df = pd.merge(df_sales, df_products, on='product_id', how='inner')

print("\nالجدول بعد دمج المبيعات مع المنتجات:")
print(merged_df)

# دمج الجدول الناتج مع بيانات العملاء باستخدام 'customer_id'
# سنستخدم 'left' join للاحتفاظ بجميع بيانات المبيعات حتى لو لم يكن العميل موجوداً في جدول العملاء
final_analytical_df = pd.merge(merged_df, df_customers, on='customer_id', how='left')

print("\nالجدول التحليلي النهائي بعد دمج بيانات العملاء أيضاً:")
print(final_analytical_df)

3. توحيد البيانات عمودياً باستخدام Concat

في بعض الأحيان، قد نحصل على بيانات جديدة بنفس هيكل البيانات الموجودة ونرغب في إضافتها عمودياً. هنا يأتي دور pd.concat().

ملاحظة تقنية: pd.concat() مفيدة لدمج DataFrames إما عمودياً (axis=0 وهو الافتراضي) أو أفقياً (axis=1). عند الدمج عمودياً، يجب أن تكون الأعمدة متطابقة أو شبه متطابقة.
# لنفترض أن لدينا بيانات مبيعات جديدة لهذا الشهر
df_new_sales = pd.DataFrame({
    'sale_id': [7, 8, 9],
    'product_id': [101, 104, 102],
    'customer_id': [1, 5, 3],
    'quantity': [1, 2, 1],
    'price': [10.0, 75.0, 25.0]
})

print("\nبيانات المبيعات الجديدة:")
print(df_new_sales)

# دمج بيانات المبيعات الجديدة عمودياً مع بيانات المبيعات الأصلية
# ignore_index=True لإعادة تعيين الفهارس بشكل صحيح بعد الدمج
all_sales_concat = pd.concat([df_sales, df_new_sales], ignore_index=True)

print("\nجميع بيانات المبيعات بعد الدمج العمودي (Concat):")
print(all_sales_concat)

# يمكننا الآن تطبيق الدمج الأفقي على جميع بيانات المبيعات الموحدة
# لإنشاء قاعدة بيانات تحليلية محدثة بالكامل
full_updated_analytical_df = pd.merge(all_sales_concat, df_products, on='product_id', how='inner')
full_updated_analytical_df = pd.merge(full_updated_analytical_df, df_customers, on='customer_id', how='left')

print("\nقاعدة البيانات التحليلية المحدثة بالكامل بعد دمج البيانات الجديدة عمودياً وأفقياً:")
print(full_updated_analytical_df)

الكود النهائي الكامل

هذا السكربت يجمع كل الخطوات المذكورة أعلاه لبناء قاعدة بيانات تحليلية شاملة.

import pandas as pd

# 1. التحضير للبيانات الأولية
# DataFrame للمبيعات
df_sales = pd.DataFrame({
    'sale_id': [1, 2, 3, 4, 5, 6],
    'product_id': [101, 102, 101, 103, 102, 101],
    'customer_id': [1, 2, 1, 3, 2, 4],
    'quantity': [2, 1, 3, 1, 2, 1],
    'price': [10.0, 25.0, 10.0, 50.0, 25.0, 10.0]
})
# DataFrame للمنتجات
df_products = pd.DataFrame({
    'product_id': [101, 102, 103, 104],
    'product_name': ['Laptop', 'Mouse', 'Keyboard', 'Monitor'],
    'category': ['Electronics', 'Electronics', 'Electronics', 'Electronics']
})
# DataFrame للعملاء
df_customers = pd.DataFrame({
    'customer_id': [1, 2, 3, 4, 5],
    'customer_name': ['Ahmed', 'Sara', 'Khalid', 'Laila', 'Nour'],
    'city': ['Riyadh', 'Jeddah', 'Dammam', 'Riyadh', 'Jeddah']
})

print("--- بيانات المبيعات الأولية ---")
print(df_sales)
print("\n--- بيانات المنتجات الأولية ---")
print(df_products)
print("\n--- بيانات العملاء الأولية ---")
print(df_customers)

# 2. دمج البيانات أفقياً باستخدام Merge (Join)
# دمج المبيعات مع المنتجات
merged_sales_products = pd.merge(df_sales, df_products, on='product_id', how='inner')
print("\n--- الجدول بعد دمج المبيعات مع المنتجات ---")
print(merged_sales_products)

# دمج الجدول الناتج مع بيانات العملاء
final_analytical_base_df = pd.merge(merged_sales_products, df_customers, on='customer_id', how='left')
print("\n--- الجدول التحليلي الأساسي بعد دمج بيانات العملاء ---")
print(final_analytical_base_df)

# 3. توحيد البيانات عمودياً باستخدام Concat
# بيانات مبيعات جديدة
df_new_sales = pd.DataFrame({
    'sale_id': [7, 8, 9],
    'product_id': [101, 104, 102],
    'customer_id': [1, 5, 3],
    'quantity': [1, 2, 1],
    'price': [10.0, 75.0, 25.0]
})
print("\n--- بيانات المبيعات الجديدة ---")
print(df_new_sales)

# دمج بيانات المبيعات الجديدة عمودياً مع بيانات المبيعات الأصلية
all_sales_combined = pd.concat([df_sales, df_new_sales], ignore_index=True)
print("\n--- جميع بيانات المبيعات بعد الدمج العمودي (Concat) ---")
print(all_sales_combined)

# إعادة بناء قاعدة البيانات التحليلية بالكامل باستخدام جميع المبيعات الموحدة
full_updated_analytical_df = pd.merge(all_sales_combined, df_products, on='product_id', how='inner')
full_updated_analytical_df = pd.merge(full_updated_analytical_df, df_customers, on='customer_id', how='left')

print("\n--- قاعدة البيانات التحليلية المحدثة بالكامل ---")
print(full_updated_analytical_df)

النتيجة المتوقعة

عند تشغيل السكربت، ستتم طباعة عدة جداول (DataFrames) إلى الشاشة في كل مرحلة من مراحل الدمج والتوحيد. الجدول النهائي full_updated_analytical_df سيحتوي على جميع بيانات المبيعات (الأصلية والجديدة) مدمجة مع تفاصيل المنتجات والعملاء. سيكون هذا الجدول شاملاً وجاهزاً للتحليل، حيث يربط معلومات المبيعات بالمنتج الذي بيع وبالعميل الذي اشتراه، مع إضافة تفاصيل مثل اسم المنتج وفئته واسم العميل ومدينته.

على سبيل المثال، سيكون جزء من الناتج النهائي مشابهًا لما يلي:

   sale_id  product_id  customer_id  quantity  price product_name     category customer_name    city
0        1         101            1         2   10.0       Laptop  Electronics         Ahmed  Riyadh
1        2         102            2         1   25.0        Mouse  Electronics          Sara  Jeddah
2        3         101            1         3   10.0       Laptop  Electronics         Ahmed  Riyadh
3        4         103            3         1   50.0     Keyboard  Electronics        Khalid  Dammam
4        5         102            2         2   25.0        Mouse  Electronics          Sara  Jeddah
5        6         101            4         1   10.0       Laptop  Electronics         Laila  Riyadh
6        7         101            1         1   10.0       Laptop  Electronics         Ahmed  Riyadh
7        8         104            5         2   75.0      Monitor  Electronics          Nour  Jeddah
8        9         102            3         1   25.0        Mouse  Electronics        Khalid  Dammam