بعد أن تتعلم قراءة ملف CSV وتحويله إلى DataFrame باستخدام مكتبة pandas، تأتي خطوة مهمة جدًا قبل أي تحليل حقيقي: تنظيف البيانات.
البيانات التي نحصل عليها من ملفات Excel أو CSV أو قواعد البيانات لا تكون دائمًا مرتبة وجاهزة. قد تجد قيمًا فارغة، أسماء أعمدة غير واضحة، أرقامًا ناقصة، أو صفوفًا غير مكتملة. لذلك لا يكفي أن تقرأ البيانات فقط، بل يجب أن تفحصها وتنظفها قبل أن تعتمد على نتائج التحليل.
في هذا الدرس من مسار تحليل البيانات ببايثون ستتعلم كيف تكتشف القيم الفارغة في pandas، وكيف تستخدم isnull() وdropna() وfillna()، ومتى تحذف القيم الناقصة ومتى تستبدلها بقيمة مناسبة.
{alertInfo} الفكرة ببساطة: تنظيف البيانات يعني فحص الجدول قبل التحليل، ومعالجة المشاكل مثل القيم الفارغة حتى لا تحصل على نتائج مضللة أو غير دقيقة.
{getToc} $title={محتوى المقال}
لماذا تنظيف البيانات مهم في تحليل البيانات؟
عند تحليل البيانات، قد تبدو الأرقام صحيحة من الخارج، لكنها قد تحتوي على مشاكل تؤثر على النتيجة النهائية. مثلًا إذا أردت حساب متوسط درجات الطلاب، وكان هناك طالب لا توجد له درجة، فماذا ستفعل؟ هل تحذف الصف؟ هل تضع صفرًا؟ هل تضع متوسط الدرجات؟
الإجابة تعتمد على نوع البيانات والهدف من التحليل. لذلك تنظيف البيانات ليس مجرد أوامر نكتبها، بل قرار منطقي قبل أن يكون خطوة برمجية.
| المشكلة | مثال | التأثير على التحليل |
|---|---|---|
| قيمة فارغة | درجة طالب غير موجودة | قد تؤثر على المتوسط أو الفرز أو التصفية. |
| اسم عمود غير واضح | col1 بدل score |
يصعب فهم البيانات والتعامل معها. |
| صف ناقص | اسم موجود لكن العمر غير موجود | قد يجعل المقارنات غير دقيقة. |
| نوع بيانات غير مناسب | رقم محفوظ كنص | قد يمنع الحسابات مثل المتوسط والمجموع. |
إنشاء بيانات للتجربة
حتى يكون الشرح واضحًا، سننشئ DataFrame بسيطًا يحتوي على بعض القيم الفارغة. في pandas تظهر القيم الفارغة غالبًا بالشكل NaN.
import pandas as pd
import numpy as np
data = {
"name": ["Ali", "Sara", "Omar", "Mona", "Khaled"],
"age": [22, 25, np.nan, 23, 24],
"city": ["Aden", "Sanaa", "Taiz", np.nan, "Hadramout"],
"score": [88, np.nan, 76, 95, 82]
}
df = pd.DataFrame(data)
print(df)
الناتج سيكون قريبًا من هذا الشكل:
name age city score
0 Ali 22.0 Aden 88.0
1 Sara 25.0 Sanaa NaN
2 Omar NaN Taiz 76.0
3 Mona 23.0 NaN 95.0
4 Khaled 24.0 Hadramout 82.0
لاحظ أن بعض الخانات تحتوي على NaN، وهذا يعني أن القيمة مفقودة أو غير موجودة.
ما معنى NaN في pandas؟
NaN تعني أن هناك قيمة مفقودة. قد تظهر بسبب أن الخلية كانت فارغة في ملف CSV، أو لأن البيانات لم تكن متوفرة عند جمعها، أو لأن هناك مشكلة أثناء إدخال البيانات.
وجود NaN ليس خطأ دائمًا، لكنه إشارة تقول لك: قبل أن تحلل البيانات، انتبه، هناك شيء ناقص يجب فحصه.
{alertWarning} لا تتعامل مع القيم الفارغة بعشوائية. حذف الصفوف أو تعبئة القيم قد يغير نتيجة التحليل، لذلك اختر الطريقة المناسبة حسب معنى البيانات.
اكتشاف القيم الفارغة باستخدام isnull
الدالة isnull() تفحص كل خلية في الجدول، وتخبرك هل هي فارغة أم لا. إذا كانت الخلية فارغة تعطي True، وإذا كانت غير فارغة تعطي False.
print(df.isnull())
الناتج سيكون جدولًا من القيم المنطقية:
name age city score
0 False False False False
1 False False False True
2 False True False False
3 False False True False
4 False False False False
هذا مفيد، لكنه قد يكون طويلًا إذا كان الجدول كبيرًا. لذلك نستخدم غالبًا sum() لمعرفة عدد القيم الفارغة في كل عمود.
print(df.isnull().sum())
الناتج:
name 0
age 1
city 1
score 1
dtype: int64
هنا نعرف أن عمود age يحتوي على قيمة فارغة واحدة، وعمود city يحتوي على قيمة فارغة واحدة، وعمود score يحتوي على قيمة فارغة واحدة.
اكتشاف القيم غير الفارغة باستخدام notnull
الدالة notnull() تعمل بالعكس. إذا كانت الخلية تحتوي على قيمة تعطي True، وإذا كانت فارغة تعطي False.
print(df.notnull())
قد تستخدمها عندما تريد اختيار الصفوف التي تحتوي على قيمة موجودة في عمود معين.
students_with_score = df[df["score"].notnull()]
print(students_with_score)
هذا الكود يعرض الطلاب الذين لديهم درجة موجودة فقط.
حذف الصفوف التي تحتوي على قيم فارغة باستخدام dropna
أسهل طريقة للتعامل مع القيم الفارغة هي حذف الصفوف التي تحتوي عليها باستخدام dropna().
clean_df = df.dropna()
print(clean_df)
الناتج سيحتوي فقط على الصفوف الكاملة التي لا تحتوي على قيم فارغة:
name age city score
0 Ali 22.0 Aden 88.0
4 Khaled 24.0 Hadramout 82.0
هذه الطريقة سريعة، لكنها قد تحذف بيانات كثيرة إذا كان الجدول كبيرًا وفيه قيم ناقصة متعددة.
{alertInfo}
استخدم dropna() بحذر. إذا كان عدد الصفوف قليلًا، فقد تخسر جزءًا مهمًا من البيانات بمجرد حذف الصفوف الناقصة.
حذف الصفوف حسب عمود معين
أحيانًا لا تريد حذف أي صف فيه أي قيمة فارغة، بل تريد حذف الصفوف فقط إذا كان عمود مهم فارغًا. مثلًا إذا كان عمود score مهمًا جدًا في التحليل، يمكن حذف الصفوف التي لا تحتوي على درجة فقط.
clean_scores = df.dropna(subset=["score"])
print(clean_scores)
بهذه الطريقة، لن نحذف الصف لمجرد أن المدينة فارغة، بل نحذف الصفوف التي لا تحتوي على قيمة في عمود score فقط.
تعبئة القيم الفارغة باستخدام fillna
بدل حذف الصفوف، يمكن تعبئة القيم الفارغة باستخدام fillna(). هذه الطريقة مفيدة عندما يكون الحذف غير مناسب.
مثال: تعبئة القيم الفارغة في عمود city بكلمة Unknown:
df["city"] = df["city"].fillna("Unknown")
print(df)
هذا يعني أن أي مدينة غير موجودة ستظهر باسم Unknown بدل NaN.
تعبئة القيم الرقمية بالمتوسط
في الأعمدة الرقمية، يمكن أحيانًا تعبئة القيمة الفارغة بمتوسط العمود. مثلًا إذا كان لدينا عمر مفقود، يمكن استخدام متوسط الأعمار:
average_age = df["age"].mean()
df["age"] = df["age"].fillna(average_age)
print(df)
وهنا يتم حساب متوسط الأعمار الموجودة، ثم استخدامه بدل العمر الفارغ.
{alertWarning} تعبئة القيم بالمتوسط ليست مناسبة دائمًا. استخدمها عندما يكون ذلك منطقيًا في سياق البيانات، ولا تستخدمها فقط لأنها سهلة.
تعبئة القيم الرقمية بقيمة ثابتة
أحيانًا تكون القيمة الثابتة أفضل من المتوسط. مثلًا إذا كان عمود score يمثل درجة اختبار، فقد تقرر أن الدرجة الفارغة تعني أن الطالب لم يدخل الاختبار، فتضع 0.
df["score"] = df["score"].fillna(0)
print(df)
لكن انتبه: وضع صفر قد يخفض المتوسط كثيرًا، لذلك يجب أن تكون متأكدًا من معنى القيمة الفارغة.
متى أحذف القيم الفارغة ومتى أعبئها؟
هذا سؤال مهم جدًا للمبتدئين في تحليل البيانات. لا توجد إجابة واحدة لكل الحالات، لكن هذا الجدول يساعدك على اتخاذ قرار مبدئي:
| الحالة | التصرف المناسب غالبًا | مثال |
|---|---|---|
| عدد القيم الفارغة قليل جدًا | يمكن حذف الصفوف الناقصة | صفان ناقصان من أصل آلاف الصفوف. |
| العمود مهم جدًا للتحليل | احذف الصفوف الناقصة في هذا العمود أو افحصها يدويًا | عمود السعر في تحليل المبيعات. |
| القيمة النصية غير معروفة | يمكن تعبئتها بكلمة مثل Unknown |
مدينة غير مسجلة. |
| القيمة الرقمية مفقودة | قد تستخدم المتوسط أو الوسيط حسب الحالة | عمر مفقود أو دخل مفقود. |
| القيمة الفارغة تعني عدم حدوث الشيء | قد تستخدم صفرًا | عدد المشتريات إذا لم يشترِ العميل شيئًا. |
فحص البيانات بعد التنظيف
بعد حذف أو تعبئة القيم الفارغة، يجب أن تفحص الجدول مرة أخرى. لا تفترض أن المشكلة انتهت دون مراجعة.
print(df.isnull().sum())
إذا كانت النتيجة كلها أصفارًا، فهذا يعني أنه لم تعد توجد قيم فارغة في الأعمدة التي فحصتها.
name 0
age 0
city 0
score 0
dtype: int64
تنظيف أسماء الأعمدة
من المشاكل الشائعة أيضًا أن تكون أسماء الأعمدة غير منظمة، مثل وجود مسافات زائدة أو اختلاف في شكل الحروف. مثلًا قد يكون اسم العمود " Score " بدل "score".
يمكن تنظيف أسماء الأعمدة بهذه الطريقة:
df.columns = df.columns.str.strip().str.lower()
print(df.columns)
هذا الكود يزيل المسافات من بداية ونهاية أسماء الأعمدة، ويحولها إلى حروف صغيرة حتى يصبح التعامل معها أسهل.
الكود الكامل للدرس
هذا مثال كامل يجمع أهم خطوات تنظيف البيانات في هذا الدرس:
import pandas as pd
import numpy as np
data = {
"name": ["Ali", "Sara", "Omar", "Mona", "Khaled"],
"age": [22, 25, np.nan, 23, 24],
"city": ["Aden", "Sanaa", "Taiz", np.nan, "Hadramout"],
"score": [88, np.nan, 76, 95, 82]
}
df = pd.DataFrame(data)
print("البيانات قبل التنظيف:")
print(df)
print("\nعدد القيم الفارغة قبل التنظيف:")
print(df.isnull().sum())
df["city"] = df["city"].fillna("Unknown")
average_age = df["age"].mean()
df["age"] = df["age"].fillna(average_age)
df["score"] = df["score"].fillna(0)
print("\nالبيانات بعد التنظيف:")
print(df)
print("\nعدد القيم الفارغة بعد التنظيف:")
print(df.isnull().sum())
ماذا تعلمت في هذا الدرس؟
| الأمر | وظيفته |
|---|---|
df.isnull() |
فحص القيم الفارغة داخل الجدول. |
df.isnull().sum() |
حساب عدد القيم الفارغة في كل عمود. |
df.notnull() |
فحص القيم الموجودة غير الفارغة. |
df.dropna() |
حذف الصفوف التي تحتوي على قيم فارغة. |
df.dropna(subset=["column"]) |
حذف الصفوف حسب وجود قيمة فارغة في عمود معين. |
df.fillna() |
تعبئة القيم الفارغة بقيمة ثابتة أو محسوبة. |
df.columns.str.strip() |
تنظيف المسافات الزائدة من أسماء الأعمدة. |
روابط داخلية مفيدة من بايثون العرب
- تحليل البيانات ببايثون للمبتدئين: من أين تبدأ؟
- أساسيات بايثون 30: التعامل مع ملفات CSV للمبتدئين
- قراءة ملفات CSV داخل مشروع بايثون بعد الأساسيات
- شرح pip في بايثون: تثبيت مكتبات بايثون وإدارة الحزم للمبتدئين
- أفضل مكتبات تحليل البيانات ببايثون
مصادر خارجية مفيدة
- دليل pandas الرسمي للتعامل مع القيم المفقودة
- توثيق dropna الرسمي في pandas
- توثيق fillna الرسمي في pandas
الخلاصة
تنظيف البيانات خطوة أساسية قبل أي تحليل باستخدام pandas. في هذا الدرس تعلمت كيف تكتشف القيم الفارغة باستخدام isnull()، وكيف تحسب عددها في كل عمود، وكيف تحذف الصفوف الناقصة باستخدام dropna() أو تعبئ القيم المفقودة باستخدام fillna().
تذكر دائمًا أن الهدف ليس إزالة NaN بأي طريقة، بل اختيار القرار الصحيح حسب معنى البيانات. أحيانًا يكون الحذف مناسبًا، وأحيانًا تكون التعبئة أفضل، وأحيانًا تحتاج إلى مراجعة مصدر البيانات نفسه.
{alertSuccess} القاعدة المهمة: لا تبدأ تحليل البيانات مباشرة بعد القراءة. افحص القيم الفارغة، راجع الأعمدة، ونظف البيانات أولًا حتى تكون النتائج أقرب إلى الواقع.
أسئلة شائعة
ما معنى القيم الفارغة في pandas؟
القيم الفارغة هي خانات لا تحتوي على بيانات، وتظهر غالبًا في pandas بالشكل NaN. وقد تكون ناتجة عن خلية فارغة في ملف CSV أو نقص في البيانات الأصلية.
ما الفرق بين isnull و notnull؟
isnull() تستخدم لاكتشاف القيم الفارغة، أما notnull() فتستخدم لاكتشاف القيم الموجودة غير الفارغة.
متى أستخدم dropna؟
استخدم dropna() عندما تكون القيم الفارغة قليلة، أو عندما يكون وجود قيمة ناقصة يجعل الصف غير صالح للتحليل.
متى أستخدم fillna؟
استخدم fillna() عندما لا تريد حذف الصفوف، وتريد استبدال القيم الفارغة بقيمة مناسبة مثل المتوسط أو كلمة Unknown أو رقم معين.
هل تعبئة القيم الفارغة بالمتوسط دائمًا صحيحة؟
لا، تعبئة القيم بالمتوسط ليست مناسبة دائمًا. يجب أن تسأل أولًا: هل المتوسط يمثل هذه القيمة فعلًا؟ وهل سيؤثر على نتيجة التحليل؟
هل يجب تنظيف البيانات قبل كل تحليل؟
نعم، من الأفضل دائمًا فحص البيانات وتنظيفها قبل التحليل، لأن القيم الفارغة أو الأعمدة غير المنظمة قد تؤدي إلى نتائج غير دقيقة.



