EduFlow
Python لتحليل البيانات
⁦0%⁩

الوحدة 2 · أساسيات pandas

تحميل ملف CSV وفحصه

18 دقراءة 4 دتمرين Python

الدرس في لمحة

حمّل ملف CSV إلى DataFrame باستخدام read_csv، وطبّق روتين فحص من خمس خطوات (shape و head و info و describe و value_counts) يلتقط المشكلات قبل أن تصل إلى أرقامك.

  1. 1الخطوة 1: حمّل الملف، ثم افحص shape و head()
  2. 2الخطوة 2: تعرض info() الأنواع والخانات الفارغة
  3. 3الخطوة 3: تلخّص describe() الأرقام
  4. 4الخطوة 4: value_counts() على الأعمدة النصية
  5. 5الخطوة 5: تحقّق مما توشك أن تفترضه

لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.

يرسل لك رئيس النمو الملف orders.csv ويطلب “رقم إيراد سريعًا”. أسرع طريقة لتقديم إجابة خاطئة هي أن تحمّل الملف وتجمع عمودًا مباشرة. كل محلل خبير يفعل الشيء نفسه أولًا: ينظر إلى البيانات. لا ينظر إليها كلها، بل يجري بضعة فحوص مقصودة تستغرق ثلاثين ثانية وتلتقط معظم المشكلات قبل أن تصل إلى شريحة عرض.

الخطوة 1: حمّل الملف، ثم افحص shape و head()

Python
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() الأنواع والخانات الفارغة

Python
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 أن تحلّلها أثناء التحميل:

Python
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() الأرقام

Python
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() على الأعمدة النصية

Python
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: تحقّق مما توشك أن تفترضه

أخيرًا، حوّل توقّعاتك إلى فحوص من سطر واحد:

Python
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.

قراءات إضافية

تحقّق من فهمك

3 أسئلة

السؤال 1 من 3

تعرض info() السطر coupon_code 388 non-null object لجدول فيه 2,066 صفًا. ماذا يخبرك ذلك؟

السؤال 2 من 3

تعرض describe() القيمة mean 300.47 للعمود customer_id. كيف تقرأ ذلك؟

السؤال 3 من 3

في customers.csv يحمل العمود referred_by معرّفات عملاء، لكنه يُحمَّل على هيئة float64. لماذا؟

تدريب

تمرين Python

افحص جدول العملاء

حمّل customers.csv إلى customers، مع تحليل signup_date كتاريخ أثناء التحميل. ثم أجب عن خمسة أسئلة بالكود: n_rows (عدد الصفوف)، وn_countries (عدد الدول المختلفة)، وtop_country (الدولة التي فيها أكبر عدد من العملاء)، وmissing_referrals (عدد الصفوف التي ليس فيها referred_by)، وfirst_signup (أقدم تاريخ تسجيل).

ملفات البيانات: customers.csv

import pandas as pd

# Load customers.csv with signup_date parsed as a date
customers = None

n_rows = None             # number of customers (rows)
n_countries = None        # how many distinct countries
top_country = None        # the country with the most customers
missing_referrals = None  # how many rows have no referred_by value
first_signup = None       # the earliest signup_date
جارٍ تحميل المحرّر…

Ctrl/⌘ + Enter للتشغيل · يعمل في بيئة معزولة داخل متصفّحك. لا شيء يغادر جهازك.

(لا مخرجات)

الفحوص

  • في customers 600 صف و9 أعمدة
  • signup_date عمود من نوع datetime
  • 600 صف و8 دول
  • الدولة الأولى هي الولايات المتحدة
  • 503 عملاء ليست لديهم إحالة
  • أول تسجيل كان في 2024-01-01