الوحدة 2 · أساسيات pandas
تحميل ملف CSV وفحصه
18 دقراءة 4 دتمرين Python
الدرس في لمحة
حمّل ملف CSV إلى DataFrame باستخدام read_csv، وطبّق روتين فحص من خمس خطوات (shape و head و info و describe و value_counts) يلتقط المشكلات قبل أن تصل إلى أرقامك.
- 1الخطوة 1: حمّل الملف، ثم افحص shape و head()
- 2الخطوة 2: تعرض info() الأنواع والخانات الفارغة
- 3الخطوة 3: تلخّص describe() الأرقام
- 4الخطوة 4: value_counts() على الأعمدة النصية
- 5الخطوة 5: تحقّق مما توشك أن تفترضه
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
يرسل لك رئيس النمو الملف orders.csv ويطلب “رقم إيراد سريعًا”. أسرع طريقة لتقديم إجابة خاطئة هي أن تحمّل الملف وتجمع عمودًا مباشرة. كل محلل خبير يفعل الشيء نفسه أولًا: ينظر إلى البيانات. لا ينظر إليها كلها، بل يجري بضعة فحوص مقصودة تستغرق ثلاثين ثانية وتلتقط معظم المشكلات قبل أن تصل إلى شريحة عرض.
الخطوة 1: حمّل الملف، ثم افحص shape و head()
import pandas as pd
orders = pd.read_csv("orders.csv")
print(orders.shape)
print(orders.head().to_string())تقرأ read_csv صف العناوين على أنه أسماء الأعمدة، وتخمّن نوع كل عمود، وتعيد DataFrame. تعرض head() أول خمسة صفوف (head(10) تعرض عشرة، وtail() تعرض الأخيرة، وsample(5) تعرض خمسة عشوائيًا، وهي أفضل في كشف الغرائب من الصفوف الأولى). أما .to_string() فتطبع كل الأعمدة بدلًا من إخفاء الوسطى منها خلف ....
2,066 صفًا و7 أعمدة. قبل أن تكمل، قل بصوت عالٍ ما تتوقّعه: صف لكل طلب، ومعرّف الطلب، والعميل، والتاريخ، والحالة، والقناة، وكوبون اختياري، ورسوم الشحن. الفحوص التالية تؤكّد كل توقّع أو تنفيه.
الخطوة 2: تعرض info() الأنواع والخانات الفارغة
import pandas as pd
orders = pd.read_csv("orders.csv")
orders.info()تطبع info() بنفسها، دون حاجة إلى print(). اقرأها عمودًا عمودًا. يخبرك Non-Null Count بعدد الصفوف التي فيها قيمة: للعمود coupon_code قيم في 388 صفًا من 2,066، فمعظم الطلبات لم تستخدم كوبونًا. ويخبرك Dtype بما فهمته pandas من كل عمود: المعرّفات int64، والرسوم float64، وكل ما عدا ذلك object، أي نص.
وهذا يشمل order_date. حين تُخزَّن التواريخ كنصوص، فإنها لا تُرتَّب ترتيبًا صحيحًا إلا لأن هذا الملف يكتبها بالسنة أولًا مصادفةً، ولا تستطيع الإجابة عن سؤال “أيّ شهر؟”. اطلب من read_csv أن تحلّلها أثناء التحميل:
import pandas as pd
orders = pd.read_csv("orders.csv", parse_dates=["order_date"])
print(orders.dtypes)
print(orders["order_date"].min(), "to", orders["order_date"].max())الآن أصبح العمود datetime64[ns]، وتؤكّد min() وmax() أن البيانات تمتد من 2 يناير 2024 إلى 30 ديسمبر 2025. فحص النطاق الزمني لكل ملف جديد عادة تستحق أن تكتسبها: شهر مفقود أو تاريخ شارد في 1970 يظهران فورًا.
الخطوة 3: تلخّص describe() الأرقام
import pandas as pd
orders = pd.read_csv("orders.csv")
print(orders.describe().round(2))تعطيك describe() العدد والمتوسط والانحراف المعياري والحد الأدنى والأرباع (quartiles) والحد الأقصى لكل عمود رقمي. رسوم الشحن تتراوح بين 0 و9.99 بوسيط 4.99: أرقام معقولة. لكنها أيضًا تعرض بأمانة متوسطًا لـ customer_id قدره 300.47، وهذا لا يعني شيئًا. المعرّفات تسميات تصادف أنها أرقام. اقرأ describe() فقط للأعمدة التي يكون للحساب فيها معنى، واستخدمها لتلتقط القيم المستحيلة: كميات سالبة، أو أسعار صفرية، أو حد أقصى يساوي مئة ضعف الوسيط.
الخطوة 4: value_counts() على الأعمدة النصية
import pandas as pd
orders = pd.read_csv("orders.csv")
print(orders["status"].value_counts())
print(orders["coupon_code"].value_counts(dropna=False))
print(orders["channel"].value_counts(normalize=True).round(3))تسرد value_counts() كل قيمة مختلفة مع عدد مرات ظهورها، الأكثر شيوعًا أولًا. بها تجد الأخطاء الكتابية ("Web" بجانب "web")، والفئات غير المتوقّعة، وحجم كل مجموعة. يُدرج dropna=False القيم المفقودة كصف مستقل، ويعطيك normalize=True الحصص بدلًا من الأعداد: 55% من الطلبات جاءت عبر الويب.
لاحظ أن 105 طلبات أُلغيت. هل يجب أن يشملها الإيراد؟ هذا قرار عمل لا قرار برمجي، وستتخذه صراحةً في القسم 4. والفحص هو المكان الذي تظهر فيه هذه القرارات لأول مرة.
الخطوة 5: تحقّق مما توشك أن تفترضه
أخيرًا، حوّل توقّعاتك إلى فحوص من سطر واحد:
import pandas as pd
orders = pd.read_csv("orders.csv")
customers = pd.read_csv("customers.csv")
print(orders["order_id"].is_unique) # one row per order?
print(orders["customer_id"].nunique(), "customers ordered")
print(len(customers), "customers in total")
print(customers["referred_by"].dtype)معرّف الطلب فريد، فالصف الواحد هو فعلًا طلب واحد. 515 عميلًا من 600 طلبوا مرة واحدة على الأقل؛ والـ 85 الآخرون سجّلوا ولم يشتروا أبدًا، وهذا مهم لاحقًا حين تحسب “الإيراد لكل عميل”. وقد حُمّل referred_by على هيئة float64 مع أنه يحمل معرّفات عملاء: معظم العملاء لم يُحالوا من أحد، فأصبحت الخانات الفارغة NaN، وNaN في pandas الكلاسيكية عدد عشري، فصار العمود كله عشريًا.
في التمرين تطبّق الروتين على customers.csv. وفي الدرس التالي تتعلّم استخراج الصفوف والأعمدة التي تحتاجها بالضبط باستخدام .loc و.iloc.
أهم النقاط
pd.read_csv("file.csv")تحمّل جدولًا؛ وparse_dates=[...]تحوّل أعمدة التواريخ إلى تواريخ حقيقية أثناء التحميل.- طبّق الروتين نفسه على كل ملف جديد -
shapeثمhead()ثمinfo()ثمdescribe()، ثمvalue_counts()على الأعمدة النصية. - تعرض
info()نوع كل عمود (dtype) وعدد قيمه غير الفارغة، فتكشف القيم المفقودة والأرقام المخزّنة كنصوص. - العمود الصحيح الذي فيه خانات فارغة يُحمَّل على هيئة
float64، لأنNaNالكلاسيكية عدد عشري. - تحقّق بالكود من الحقائق التي ستعتمد عليها، مثل أن المعرّف فريد، بسطر مثل
orders["order_id"].is_unique.