لحذف الصفوف المكررة من ملف Excel باستخدام بايثون، اقرأ الملف باستخدام pd.read_excel() ثم استخدم drop_duplicates() واحفظ النتيجة في ملف جديد. وإذا كان التكرار يُحدد بواسطة عمود مثل رقم العميل أو الفاتورة، استخدم subset بدل مقارنة الصف كاملًا.
سنستخدم ملف عملاء واقعيًا، ونفحص التكرار قبل حذفه، ثم نجرّب التكرار حسب عمود واحد أو عدة أعمدة ونوضح الفرق بين keep="first" وkeep="last" وkeep=False.
{alertWarning}
قبل التجربة: لا تكتب فوق ملف Excel الأصلي في أول تشغيل. احتفظ بنسخة احتياطية واحفظ النتيجة باسم جديد مثل customers_cleaned.xlsx حتى تتأكد أن قاعدة حذف التكرار صحيحة.
{getToc} $title={محتوى المقال}
تثبيت Pandas وopenpyxl
سنستخدم Pandas لمعالجة البيانات وopenpyxl لقراءة وكتابة ملفات .xlsx.
python -m pip install pandas openpyxl
مثالنا: ملف عملاء يحتوي سجلات مكررة
لنفترض أن لدينا ملفًا باسم customers.xlsx بالشكل التالي:
| customer_id | name | city | |
|---|---|---|---|
| C001 | Ali | ali@example.com | Aden |
| C002 | Sara | sara@example.com | Sanaa |
| C001 | Ali | ali@example.com | Aden |
| C003 | Omar | فارغ | Taiz |
| C004 | Mona | mona@example.com | Aden |
| C003 | Omar | فارغ | Taiz |
| C005 | Noor | noor@example.com | Aden |
| C005 | Noor | noor@example.com | Sanaa |
لدينا صفوف متطابقة بالكامل، ولدينا أيضًا سجلان لهما customer_id نفسه لكن قيمة city مختلفة. لذلك قبل أي حذف يجب أن تحدد ما معنى «المكرر» في بياناتك.
قراءة ملف Excel واكتشاف الصفوف المكررة
import pandas as pd
df = pd.read_excel(
"customers.xlsx"
)
duplicates = df[
df.duplicated(
keep=False
)
]
print(duplicates)
duplicated(keep=False) تعرض جميع الصفوف التي لها نسخة مطابقة أخرى. لم نحذف شيئًا بعد؛ نحن نفحص النتيجة أولًا.
حذف الصفوف المتطابقة بالكامل
cleaned_df = df.drop_duplicates()
cleaned_df.to_excel(
"customers_cleaned.xlsx",
index=False
)
بدون subset تقارن Pandas جميع الأعمدة. لذلك سيُحذف الصف المتطابق تمامًا، لكن السجلان C005 سيبقيان لأن قيمة city مختلفة.
شكل البيانات بعد حذف الصفوف المتطابقة
| customer_id | name | city | |
|---|---|---|---|
| C001 | Ali | ali@example.com | Aden |
| C002 | Sara | sara@example.com | Sanaa |
| C003 | Omar | فارغ | Taiz |
| C004 | Mona | mona@example.com | Aden |
| C005 | Noor | noor@example.com | Aden |
| C005 | Noor | noor@example.com | Sanaa |
حذف التكرار حسب عمود واحد
إذا كان customer_id يجب أن يكون فريدًا، استخدمه داخل subset:
cleaned_df = df.drop_duplicates(
subset=["customer_id"],
keep="first"
)
cleaned_df.to_excel(
"customers_by_id.xlsx",
index=False
)
الآن تعتبر Pandas أي صفين لهما customer_id نفسه مكررين حتى لو اختلفت أعمدة أخرى.
{alertWarning} لا تستخدم عمودًا داخلsubsetقبل أن تتأكد أنه يمثل هوية السجل فعلًا. عمود مثلcityلا يصلح عادةً، لأن وجود عدة عملاء من Aden ليس تكرارًا.
حذف التكرار حسب عدة أعمدة
إذا لم يكن لديك ID واحد، يمكن تعريف التكرار بمجموعة أعمدة مثل الاسم والبريد:
cleaned_df = df.drop_duplicates(
subset=[
"name",
"email"
],
keep="first"
)
هنا تعتمد المقارنة فقط على name وemail، وليس على city أو بقية الأعمدة.
الفرق بين keep="first" وkeep="last" وkeep=False
| القيمة | السلوك |
|---|---|
keep="first" | تحتفظ بأول سجل وتحذف النسخ التالية. |
keep="last" | تحتفظ بآخر سجل وتحذف النسخ السابقة. |
keep=False | تحذف جميع السجلات التابعة للمجموعة المكررة. |
first_only = df.drop_duplicates(
subset=["customer_id"],
keep="first"
)
last_only = df.drop_duplicates(
subset=["customer_id"],
keep="last"
)
unique_only = df.drop_duplicates(
subset=["customer_id"],
keep=False
)
إذا كانت الصفوف مرتبة زمنيًا من الأقدم إلى الأحدث، فقد يكون keep="last" مناسبًا للاحتفاظ بأحدث سجل. لكن لا تفترض ذلك ما لم يكن ترتيب الملف موثوقًا.
keep=False لا يعني «احذف النسخ واترك واحدة»، بل يحذف كل السجلات التي تنتمي إلى مجموعة مكررة.
كيف تؤثر القيم الفارغة على التكرار؟
عند استخدام عمود يحتوي قيمًا مفقودة داخل subset، قد تُعامل الصفوف ذات القيم المفقودة كمكررة وفق قاعدة المقارنة. لذلك إذا كان البريد الإلكتروني اختياريًا، فلا تستخدم email وحده كمفتاح لتعريف العميل.
cleaned_df = df.drop_duplicates(
subset=["email"],
keep="first"
)
الأفضل اختيار ID موثوق، أو مجموعة أعمدة تمثل هوية السجل منطقيًا.
معرفة عدد الصفوف التي تم حذفها
before = len(df)
cleaned_df = df.drop_duplicates(
subset=["customer_id"],
keep="first"
)
after = len(cleaned_df)
print(
f"تم حذف: {before - after}"
)
هذه المعلومة تساعدك على مراجعة النتيجة قبل اعتماد الملف الجديد.
نسخة عملية كاملة وآمنة
السكربت التالي يقرأ ملف العملاء، يتحقق من وجود عمود المفتاح، يعرض عدد الصفوف المكررة، ويحفظ النتيجة في ملف جديد دون الكتابة فوق الملف الأصلي:
from pathlib import Path
import pandas as pd
INPUT_FILE = Path(
"customers.xlsx"
)
OUTPUT_FILE = Path(
"customers_cleaned.xlsx"
)
KEY_COLUMNS = [
"customer_id"
]
if not INPUT_FILE.is_file():
raise FileNotFoundError(
f"File not found: {INPUT_FILE}"
)
if INPUT_FILE.resolve() == OUTPUT_FILE.resolve():
raise ValueError(
"Output file must be different "
"from the original file."
)
df = pd.read_excel(
INPUT_FILE
)
missing_columns = [
column
for column in KEY_COLUMNS
if column not in df.columns
]
if missing_columns:
raise ValueError(
f"Missing columns: "
f"{missing_columns}"
)
duplicates = df[
df.duplicated(
subset=KEY_COLUMNS,
keep=False
)
].copy()
print(
f"Duplicate rows: "
f"{len(duplicates)}"
)
before = len(df)
cleaned_df = df.drop_duplicates(
subset=KEY_COLUMNS,
keep="first"
).copy()
after = len(cleaned_df)
cleaned_df.to_excel(
OUTPUT_FILE,
index=False
)
print(
f"Rows before: {before}"
)
print(
f"Rows after: {after}"
)
print(
f"Removed: {before - after}"
)
print(
f"Saved to: {OUTPUT_FILE}"
)
بهذا لديك نسخة قابلة للتشغيل تحافظ على الأصل، وتتحقق من العمود الذي ستبني عليه قرار الحذف.
كيف تختبر النتيجة قبل اعتمادها؟
- افتح
customers_cleaned.xlsxولا تحذف الملف الأصلي. - راجع عدة IDs كانت مكررة يدويًا.
- قارن عدد الصفوف قبل وبعد.
- تأكد أن العمود المستخدم في
subsetيمثل السجل فعلًا. - إذا استخدمت
keep="last"، تحقق أن ترتيب الصفوف يعكس الأقدم ثم الأحدث. - راجع القيم الفارغة في أعمدة المفتاح.
أخطاء شائعة
اختيار مفتاح غير مناسب
تكرار الاسم أو المدينة لا يعني أن السجل مكرر. استخدم ID أو مجموعة أعمدة ذات معنى واضح.
الاعتقاد أن drop_duplicates() تحذف كل تكرار منطقي
بدون subset يجب أن تكون الصفوف متطابقة في جميع الأعمدة. إذا اختلفت قيمة واحدة فلن تكون نسخة كاملة.
الكتابة فوق الملف الأصلي
احفظ الناتج باسم جديد في أول تجربة، ثم راجعه يدويًا.
Missing optional dependency 'openpyxl'
ثبت openpyxl من نفس بيئة بايثون التي تشغل منها السكربت.
PermissionError عند الحفظ
قد يكون ملف Excel الناتج مفتوحًا في Excel. أغلقه ثم أعد التشغيل.
توقع الحفاظ الكامل على تنسيق Excel
Pandas ممتازة لمعالجة البيانات الجدولية، لكن to_excel() لا تضمن الحفاظ على كل تنسيقات Workbook الأصلية والصور والخلايا المدمجة.
الصفوف تبدو مكررة لكنها لا تُحذف
قد تبدو القيم متطابقة في Excel لكنها تختلف فعليًا بسبب مسافات زائدة أو اختلاف حالة الأحرف. قبل حذف التكرار يمكنك تنظيف الأعمدة النصية المهمة:
df["name"] = df["name"].str.strip()
df["email"] = (
df["email"]
.str.strip()
.str.lower()
)
استخدم str.lower() فقط عندما يكون تجاهل حالة الأحرف منطقيًا للبيانات، مثل مقارنة عناوين البريد الإلكتروني.
روابط داخلية مفيدة من بايثون العرب
- دمج ملفات Excel متعددة في ملف واحد باستخدام بايثون وPandas — مفيد عندما تظهر التكرارات بعد جمع تقارير متعددة.
- مقارنة ملفين Excel واستخراج الصفوف الجديدة والمعدلة والمحذوفة — للانتقال من تنظيف ملف واحد إلى مقارنة إصدارين من البيانات.
- اختيار الصفوف والأعمدة في Pandas باستخدام loc وiloc — لفهم التصفية واختيار البيانات قبل المعالجة.
مصادر رسمية للتوسع
- توثيق DataFrame.drop_duplicates الرسمي
- توثيق DataFrame.duplicated الرسمي
- توثيق pandas.read_excel الرسمي
- توثيق DataFrame.to_excel الرسمي
الخلاصة
لحذف الصفوف المكررة من Excel باستخدام بايثون وPandas، ابدأ بقراءة الملف باستخدام pd.read_excel() وافحص التكرار باستخدام duplicated(). بعد ذلك استخدم drop_duplicates() للصفوف المتطابقة أو حدد subset إذا كان التكرار يعتمد على ID أو مجموعة أعمدة.
اختر keep="first" أو keep="last" حسب معنى ترتيب البيانات، واستخدم keep=False فقط عندما تريد حذف جميع السجلات المكررة. والأهم: احفظ النتيجة في ملف جديد وراجعها قبل استبدال الأصل.
{alertSuccess}
القاعدة المهمة: دالة drop_duplicates() سهلة؛ الجزء الحاسم هو تعريف معنى «السجل المكرر» بشكل صحيح. حدد المفتاح أولًا، افحص التكرارات، ثم احذف.
أسئلة شائعة
كيف أحذف الصفوف المكررة من Excel باستخدام بايثون؟
اقرأ الملف باستخدام pd.read_excel() ثم استخدم df.drop_duplicates() واحفظ النتيجة باستخدام to_excel().
كيف أحذف التكرار حسب عمود معين؟
استخدم drop_duplicates(subset=["column_name"]) وتأكد أن العمود يمثل قاعدة التكرار المطلوبة.
كيف أحذف التكرار بناءً على أكثر من عمود؟
مرر قائمة أعمدة إلى subset مثل subset=["name", "email"].
كيف أحذف كل الصفوف المكررة ولا أحتفظ بأول نسخة؟
استخدم keep=False. هذا يحذف جميع السجلات التابعة للمجموعة المكررة بحسب الأعمدة المختارة.
هل يمكن حفظ النتيجة في ملف Excel جديد؟
نعم، وهذا هو الخيار الأفضل في أول تجربة. استخدم to_excel("customers_cleaned.xlsx", index=False).
هل القيم الفارغة تؤثر على اكتشاف التكرار؟
نعم، خصوصًا إذا كانت داخل الأعمدة المستخدمة في subset. لا تستخدم عمودًا كثير القيم المفقودة كمفتاح وحيد إذا كانت الخانة الفارغة لا تعني أن السجلات متطابقة.


