سنقرأ ملف Iris ونسأل: كيف يختلف متوسط طول البتلة بين فئات الزهور الموجودة فيه؟ يوضح البرنامج طريقة قراءة CSV وفحص صفوفه وحساب الملخص وإنتاج رسم، باستخدام مكتبة Python القياسية. النتيجة تصف هذا الملف، ولا تمثل دقة مصنف أو حكماً على جميع النباتات. يمكنك نقل الخطوات إلى Notebook لاحقاً مع الاحتفاظ بالمصدر والسؤال نفسيهما.

ثبّت المصدر ومعنى الأعمدة

تتيح صفحة Iris في UCI البيانات ووصف متغيراتها وترخيص CC BY 4.0. نزّل الأرشيف من الصفحة، وفكّه إلى مجلد data واحتفظ بالملف iris.data دون تحرير. سجّل المصدر وتاريخ التنزيل والترخيص في README وانسب البيانات إلى مرجعها كما توضح الصفحة.

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

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

احفظ الآتي باسم analysis.py وشغله من المجلد الذي يحتوي data. يرفض البرنامج صفوفًا ذات بنية خاطئة بدل إسقاطها بصمت. ويُظهر عدد الصفوف المرفوضة بسبب قيمة ناقصة حتى لا يتغير مقام المتوسط دون تفسير.

import csv
from collections import defaultdict
from pathlib import Path
from statistics import mean
from html import escape

groups = defaultdict(list)
missing = 0
source = Path("data/iris.data")
with source.open(encoding="utf-8", newline="") as handle:
    for line_number, row in enumerate(csv.reader(handle), 1):
        if not row:
            continue
        if len(row) != 5:
            raise ValueError(f"Invalid row {line_number}")
        if any(value.strip() in ("", "?") for value in row):
            missing += 1
            continue
        values = [float(value) for value in row[:4]]
        if any(value <= 0 for value in values):
            raise ValueError(f"Non-positive value: {line_number}")
        groups[row[4].strip()].append(values[2])
if not groups:
    raise ValueError("No usable data")
summary = [(name, len(values), mean(values))
           for name, values in sorted(groups.items())]
with Path("summary.csv").open("w", encoding="utf-8", newline="") as handle:
    writer = csv.writer(handle)
    writer.writerow(["class", "count", "mean_petal_length_cm"])
    writer.writerows(summary)
bars = []
for index, (name, count, average) in enumerate(summary):
    y = 40 + index * 70
    bars.append(
        f'<text x="10" y="{y}">{escape(name)}</text>'
        f'<rect x="200" y="{y-18}" width="{average*60}" '
        f'height="24" fill="#235b91"/>'
        f'<text x="560" y="{y}">{average:.2f} cm</text>')
Path("summary.svg").write_text(
    '<svg xmlns="http://www.w3.org/2000/svg" '
    'viewBox="0 0 680 260" role="img">'
    '<title>Mean petal length by Iris class</title>'
    + "".join(bars) + '</svg>', encoding="utf-8")
print("Usable rows:", sum(item[1] for item in summary))
print("Rows excluded for missing values:", missing)

توضح وثائق csv أن القراءة تعيد قيمًا نصية، لذلك يحوّل البرنامج الحقول العددية صراحة. كما يستخدم newline="" عند قراءة CSV وكتابته. الرسم مخرج SVG محلي يمكن فتحه بالمتصفح؛ الأسماء والأرقام تظل متاحة أيضًا في ملف الملخص.

في تشغيل التحقق لهذا المثال على Python 3.12.10 وملف iris.data من أرشيف UCI، قُبل 150 صفًا ولم تستبعد صفوف لقيم ناقصة، واحتوت كل فئة على 50 صفًا. أُنتج ملفا الملخص والرسم. هذه نتيجة فحص هذا الملف والبرنامج، ولا تمثل قياس دقة نموذج أو تجربة على بيانات أخرى.

ماذا نفعل إذا ظهرت بيانات ناقصة؟

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

فسّر الرسم دون تجاوز ما تثبته البيانات

اقرأ summary.csv قبل الحكم من شكل الأعمدة. المتوسط يخفي تشتت القياسات؛ يمكن أن تختلف مجموعتان في المتوسط مع وجود تداخل بينهما. أضف الوسيط والمدى أو توزيعًا نقطيًا إذا كان السؤال يتطلب ذلك، ولا تستنتج علاقة سببية من مقارنة وصفية. وجود قياسات لأزهار لا يبرهن وحده صلاحية تطبيق تصنيف على صور هواتف مختلفة.

اكتب في التقرير: الملف المستخدم، وعدد الصفوف المقبولة والمستبعدة، والوحدة، وطريقة التجميع، وما يظهر في المقارنة، وحدود العينة. لا تضف نسبة دقة لأن البرنامج لا يبني مصنفًا. إذا أردت تدريب نموذج، انتقل إلى تقسيم البيانات وتقييم النموذج بخطة منفصلة.

ما الذي يسلمه مشروع تحليل قابل للمراجعة؟

  • سؤال محدد ووصف مصدر البيانات وترخيصها.
  • الملف الخام أو رابط تنزيله وبصمته، دون بيانات شخصية غير لازمة.
  • برنامج التحليل وإصدار Python وتعليمة التشغيل.
  • ملخص جدولي ورسم وعرض لتفسير النتائج والقيود.
  • سجل يوضح معالجة القيم الناقصة وأي تغييرات على البيانات.

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

المصادر

مراجعة المصادر: .

اختبار المثال وحدوده

شُغّل البرنامج على Python 3.12.10 باستخدام iris.data من أرشيف UCI: 150 صفًا مقبولًا، دون قيم ناقصة، وثلاث فئات بواقع 50 صفًا، وأُنتج summary.csv وsummary.svg. بصمة ملف البيانات SHA-256: 6f608b71a7317216319b4d27b4d9bc84e6abd734eda7872b71a458569e2656c0.

مقالات ذات صلة

الخدمة المرتبطة: مشاريع الذكاء الاصطناعي وتحليل البيانات.

أرسل متطلبات مشروعك