Pandas & NumPy Academy · درس

اكتشاف التكرارات وإزالتها

اعثر على التكرارات التامة والجزئية باستخدام duplicated() وdrop_duplicates()، وقرّر أي سجل مكرر ينبغي الاحتفاظ به.

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

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

لماذا تهم السجلات المكررة؟

تؤدي الصفوف المكررة إلى تضخيم الأعداد وإجماليات الإيرادات والمتوسطات دون ظهور أي رسالة خطأ. فمجموعة بيانات مبيعات تحتوي على 500 سجل طلب مكرر ستبالغ في تقدير الإيرادات بمجموع قيم تلك الطلبات الـ500 بالضبط. ويُعد اكتشاف السجلات المكررة وإزالتها من أولى خطوات التنظيف التي ينبغي تنفيذها، قبل أي تجميع أو نمذجة، لأن الأخطاء اللاحقة تتفاقم انطلاقًا من مصدر الفساد الواحد هذا.

import pandas as pd

df = pd.read_csv('orders.csv')
print('Shape before dedup:', df.shape)
print('Exact duplicates:', df.duplicated().sum())

العثور على السجلات المكررة تمامًا

تعيد df.duplicated() سلسلة منطقية تكون قيمتها True لكل صف يمثل نسخة مطابقة تمامًا لصف سابق. ويحدد الإعداد الافتراضي keep='first' جميع التكرارات باستثناء الظهور الأول. أما تمرير keep=False فيحدد كل ظهور مكرر، وهو مفيد عند الرغبة في فحص جميع نسخ السجل المكرر قبل تحديد النسخة التي يجب الاحتفاظ بها.

# Mark only the second+ occurrences
partial_dups = df[df.duplicated(keep='first')]
print('Rows to remove:', len(partial_dups))

# Mark ALL copies of any duplicate
all_dups = df[df.duplicated(keep=False)]
print('Rows involved in duplicates:', len(all_dups))

حذف السجلات المكررة تمامًا

أزل الصفوف المكررة تمامًا باستخدام df.drop_duplicates(). يحتفظ هذا الأسلوب افتراضيًا بالظهور الأول ويحذف جميع الظهورات الأخرى. مرّر keep='last' للاحتفاظ بأحدث سجل إذا كانت بياناتك تتضمن طابعًا زمنيًا وكانت الصفوف اللاحقة تُعد أكثر موثوقية. تحقق دائمًا من عدد الصفوف قبل العملية وبعدها للتأكد من إزالة العدد المتوقع من الصفوف.

df_clean = df.drop_duplicates(keep='first')

print('Rows removed:', len(df) - len(df_clean))
print('Shape after dedup:', df_clean.shape)

التكرارات الجزئية: بالاعتماد على المفتاح

قد تكون الصفوف نسخًا جزئية مكررة: إذ تشترك في مفتاح أعمال (مثل order_id)، لكنها تختلف في أعمدة أخرى بسبب خطأ في النظام المصدر أدّى إلى إنشاء نسختين من السجل نفسه. استخدم df.duplicated(subset=['order_id']) للعثور على الصفوف التي لها المفتاح نفسه، لكن قد تختلف قيمها في الأعمدة الأخرى. افحص هذه الصفوف قبل تحديد كيفية تسويتها.

key_dups = df[df.duplicated(subset=['order_id'], keep=False)]
print('Orders with duplicate IDs:')
print(key_dups.sort_values('order_id').head(10))

اختيار النسخة المكررة التي يجب الإبقاء عليها

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

# Keep the record with the latest update timestamp
df_sorted = df.sort_values('updated_at', ascending=False)
df_dedup = df_sorted.drop_duplicates(subset=['order_id'], keep='first')

print('Kept:', len(df_dedup), 'unique orders')

اكتشاف النسخ شبه المكررة

النسخ شبه المكررة هي صفوف تمثل الكيان نفسه لكنها تختلف اختلافًا طفيفًا — مثل اسم العميل نفسه مع خطأ إملائي، أو المعاملة نفسها مع فرق سنت واحد ناتج عن التقريب. لا يكتشف البحث عن التكرارات المطابقة تمامًا هذه الحالات. تتمثل إحدى الطرق في التجميع حسب عمود المفتاح وإجراء العدّ: فإذا ظهر اسم العميل بصيغ مختلفة قليلًا، فاستخدم .str.strip().str.lower() لتوحيد الصيغة قبل إزالة التكرارات.

df['customer_normalized'] = df['customer_name'].str.strip().str.lower()

near_dups = df.groupby('customer_normalized').size().sort_values(ascending=False)
print(near_dups[near_dups > 1].head())

إزالة التكرارات باستخدام التجميع مع GroupBy

عندما تحتاج إلى دمج الصفوف المكررة بدلًا من حذفها ببساطة، استخدم groupby().agg(). على سبيل المثال، إذا كان صفّان يمثلان الطلب نفسه، لكن أحدهما يحتوي على عنوان الشحن والآخر على عنوان الفوترة، فيمكنك التجميع باستخدام 'first' (مع تفضيل القيم غير الفارغة) أو باستخدام دالة مخصصة تدمج القيم غير الفارغة عبر الصفوف المكررة.

def coalesce(*args):
    for a in args:
        if pd.notna(a):
            return a
    return None

df_merged = df.groupby('order_id').agg(
    customer=('customer_name', 'first'),
    amount=('amount', 'max'),
    date=('order_date', 'min')
).reset_index()
print(df_merged.head())

التحقق من تأثر النتائج بترتيب الصفوف

تعتمد نتيجة drop_duplicates(keep='first') على ترتيب الصفوف. فإذا حُمّل DataFrame من استعلام قاعدة بيانات من دون عبارة ORDER BY، فسيكون ترتيب الصفوف غير حتمي، ما يعني أن السجل المُبقى قد يختلف من تشغيل إلى آخر. رتّب البيانات دائمًا وفق مفتاح ثابت (مثل المفتاح الأساسي أو الطابع الزمني) قبل إزالة التكرارات، لجعل العملية حتمية وقابلة لإعادة الإنتاج.

# Sort by primary key before deduplication for deterministic results
df = df.sort_values('order_id').reset_index(drop=True)
df_clean = df.drop_duplicates(subset=['order_id'], keep='first')

print('Deterministic dedup complete.')

التحقق من نتيجة إزالة التكرارات

بعد إزالة التكرارات، تحقّق من النتيجة عبر ثلاثة فحوصات: عدم وجود تكرارات مطابقة تمامًا (df_clean.duplicated().sum() == 0)، وعدم وجود مفاتيح أعمال مكررة (df_clean.duplicated(subset=['order_id']).sum() == 0)، وأن يكون عدد الصفوف المتوقع معقولًا. اكتب هذه الفحوصات على شكل assertions كي تفشل بوضوح إذا أدت تغيّرات البيانات المستقبلية إلى إبطال منطق التنظيف.

assert df_clean.duplicated().sum() == 0, 'Exact duplicates remain'
assert df_clean.duplicated(subset=['order_id']).sum() == 0, 'Duplicate order IDs remain'
print('Deduplication verified. Rows:', len(df_clean))

توثيق التكرارات التي أزيلت

يكون تنظيف البيانات الجيد قابلًا لإعادة الإنتاج وقابلًا للتدقيق. سجّل عدد الصفوف التي أزيلت، ومفتاح إزالة التكرارات، وقاعدة كسر التعادل في قاموس تقرير التنظيف. احفظ هذا التقرير إلى جانب ملف البيانات النظيفة، حتى يتمكن أي شخص يشغّل مسار المعالجة لاحقًا من التحقق من قرارات التنظيف دون إعادة قراءة الشيفرة. وتبني الشفافية في تنظيف البيانات الثقة في نتائج التحليل.

cleaning_log = {
    'original_rows': len(df),
    'dedup_key': 'order_id',
    'tiebreak': 'keep first by updated_at desc',
    'rows_removed': len(df) - len(df_clean),
    'clean_rows': len(df_clean)
}
for k, v in cleaning_log.items():
    print(f'{k}: {v}')

حفظ مجموعة البيانات بعد إزالة التكرارات

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

from datetime import date

output_path = f'orders_clean_{date.today()}.parquet'
df_clean.to_parquet(output_path, index=False)
print(f'Saved {len(df_clean)} rows to {output_path}')

تحقق سريع

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

مراجعة الدرس

تعلّمت في هذا الدرس: اكتشاف التكرارات المطابقة تمامًا والجزئية باستخدام duplicated() و drop_duplicates()، واختيار النسخة المكررة التي يجب الإبقاء عليها باستخدام استراتيجيات الفرز والتجميع، والتحقق من النتائج باستخدام assertions وتسجيل قرارات التنظيف. في القسم التالي، سنستكشف تقنيات اكتشاف القيم الشاذة ومعالجتها.

البدء مجانًا

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

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

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

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

هل درس «اكتشاف التكرارات وإزالتها» مجاني؟

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

ماذا ستتعلم في «اكتشاف التكرارات وإزالتها»؟

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

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

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

كم من الوقت يستغرق درس «اكتشاف التكرارات وإزالتها»؟

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

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

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

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

  1. اكتشاف التكرارات وإزالتها
  2. اكتشاف القيم الشاذة ومعالجتها
  3. توحيد الفئات غير المتسقة
  4. التحقق من المخطط والتأكيدات
← العودة إلى Pandas & NumPy Academy