تنظيم خطوات التحويل في صورة دوال
قسّم دفتر الملاحظات إلى دوال للاستخراج والتحويل والتحميل، بحيث تقبل كل دالة DataFrame وتعيده لتسهيل الاختبار.
تنظيم خطوات التحويل في صورة دوال درس مجاني في Pandas & NumPy Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Pandas & NumPy Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.
تجاوز دفاتر الملاحظات
تُعد دفاتر Jupyter رائعة للاستكشاف، لكنها غير مناسبة لمسارات البيانات في بيئة الإنتاج. فالشيفرة المبعثرة عبر 50 خلية، مع حالة عامة ومن دون اختبارات، هشة: إذ قد يؤدي تغيير خلية واحدة إلى تعطيل خلية أخرى بصمت. والبديل الاحترافي هو استخراج كل تحويل في دالة مسماة تستقبل DataFrame وتعيد DataFrame. ويمثل هذا الفصل بين المسؤوليات أساس شيفرة هندسة البيانات القابلة للصيانة.
# Notebook-style (fragile)
df = pd.read_csv('orders.csv')
df = df.dropna(subset=['revenue'])
df = df[df['quantity'] > 0]
df['revenue_per_unit'] = df['revenue'] / df['quantity']
# Function-style (robust)
def extract(path):
return pd.read_csv(path)
def transform(df):
return (
df.dropna(subset=['revenue'])
.query('quantity > 0')
.assign(revenue_per_unit=lambda d: d['revenue'] / d['quantity'])
)
df = transform(extract('orders.csv'))نمط ETL: الاستخراج والتحويل والتحميل
يقسم نمط ETL مسار البيانات إلى ثلاث مراحل: الاستخراج (القراءة من المصدر)، والتحويل (التنظيف والإثراء)، والتحميل (الكتابة إلى الوجهة). وتكون كل مرحلة دالة منفصلة. ويسهّل هذا الفصل تبديل مصادر البيانات (CSV مقابل قاعدة بيانات)، أو تغيير منطق التنظيف، أو تغيير تنسيق الإخراج من دون المساس بالمرحلتين الأخريين. وينبغي لكل مسار إنتاج اتباع هذا الهيكل.
def extract(config):
return pd.read_csv(config['input_path'], parse_dates=['order_date'])
def transform(df, config):
return (
df
.dropna(subset=config['required_cols'])
.query('quantity > 0')
.assign(revenue=lambda d: d['quantity'] * d['unit_price'])
)
def load(df, config):
df.to_parquet(config['output_path'], index=False)
print(f'Saved {len(df)} rows.')مبدأ المسؤولية الواحدة
ينبغي لكل دالة تحويل أن تنفذ مهمة واحدة بالضبط. يصعب اختبار دالة باسم clean_data() وتصحيح أخطائها إذا كانت تحذف القيم الفارغة، وتحد القيم الشاذة، وتحلل التواريخ، وترمّز الفئات. بدلًا من ذلك، اكتبوا drop_nulls() وcap_outliers() وparse_dates() وencode_categories() بوصفها دوال منفصلة. وتجعل هذه الدرجة من التفصيل تخطي أي خطوة مفردة أو استبدالها أو إعادة ترتيبها أمرًا سهلًا.
def drop_null_rows(df, required_cols):
return df.dropna(subset=required_cols)
def remove_returns(df):
return df[df['quantity'] > 0]
def compute_revenue(df):
return df.assign(revenue=lambda d: d['quantity'] * d['unit_price'])
def add_date_features(df):
return df.assign(
year=lambda d: d['order_date'].dt.year,
month=lambda d: d['order_date'].dt.month
)ربط الخطوات باستخدام pipe()
اربطوا الدوال ذات المسؤولية الواحدة باستخدام pipe() لإنشاء مرحلة التحويل الكاملة في صورة سلسلة واضحة. وتُقرأ السلسلة كأنها وصفة: كل سطر خطوة، وسهم تدفق البيانات يتجه من الأعلى إلى الأسفل. ويمكن التعليق على أي خطوة أو إعادة ترتيبها من دون إعادة تسمية المتغيرات. وتكون النتيجة النهائية DataFrame نظيفًا ومُثرى، جاهزًا لمرحلة التحميل.
import pandas as pd
REQUIRED = ['order_id', 'revenue', 'order_date']
def transform(raw_df):
return (
raw_df
.pipe(drop_null_rows, required_cols=REQUIRED)
.pipe(remove_returns)
.pipe(compute_revenue)
.pipe(add_date_features)
)
df_clean = transform(pd.read_csv('orders.csv', parse_dates=['order_date']))
print(df_clean.shape)إرجاع أعداد الصفوف لأغراض التدقيق
ينبغي لكل دالة تحويل أن تسجل اختياريًا عدد الصفوف التي استقبلتها وعدد الصفوف التي أعادتها. إن تغليف جسم الدالة بسجل لعدد الصفوف قبل التنفيذ وبعده يوفر سجل تدقيق خفيفًا يتيح لكم معرفة الموضع الذي تُسقط فيه الصفوف بسرعة أثناء تشغيل المسار. خزّنوا هذه الأعداد في قائمة واطبعوها في صورة تقرير عند نهاية كل عملية تشغيل.
audit_log = []
def audited(func):
def wrapper(df, *args, **kwargs):
before = len(df)
result = func(df, *args, **kwargs)
after = len(result)
audit_log.append({'step': func.__name__, 'in': before, 'out': after, 'dropped': before - after})
return result
return wrapper
@audited
def drop_null_rows(df, required_cols):
return df.dropna(subset=required_cols)دوال قابلة للاختبار باستخدام DataFrame صغيرة
تتمثل أكبر ميزة للدوال المسماة في قابليتها للاختبار. اكتبوا DataFrame صغيرة للاختبار تمثل حالة طرفية واقعية، ثم تحققوا من ناتج الدالة. اختبروا الدالة drop_null_rows باستخدام صف واحد يحتوي على قيمة فارغة وتحققوا من حذفه، وصف آخر لا يحتوي على قيمة فارغة وتحققوا من إبقائه. تكشف الاختبارات الوحداتية لدوال التحويل حالات التراجع عند تغيير شيفرة المسار.
import pandas as pd
def test_drop_null_rows():
test_df = pd.DataFrame({
'order_id': [1, 2, 3],
'revenue': [100.0, None, 200.0]
})
result = drop_null_rows(test_df, required_cols=['revenue'])
assert len(result) == 2, 'Should have 2 non-null rows'
assert result['revenue'].isna().sum() == 0, 'No nulls in revenue'
print('test_drop_null_rows PASSED')
test_drop_null_rows()تنظيم الدوال في وحدات
مع نمو المسار، قسّموا الدوال إلى ملفات وحدات Python: extract.py وtransform.py وload.py وvalidate.py. ويستوردها البرنامج النصي الرئيسي pipeline.py وينسق عملها. ويتميز هيكل الملفات هذا بسهولة القراءة، وقابليته للاختبار باستخدام pytest، وإمكانية نشره كحزمة Python. كما أنه يحاكي التخطيط القياسي الذي تستخدمه فرق هندسة البيانات عند استخدام أدوات مثل dbt أو Airflow.
# pipeline.py
# from extract import extract_orders
# from transform import transform
# from load import load_to_parquet
# from validate import validate_sales_df
# def run_pipeline(config):
# raw = extract_orders(config)
# clean = transform(raw, config)
# validate_sales_df(clean)
# load_to_parquet(clean, config)
print('Module-based pipeline structure shown above (imports commented for demo)')قابلية التكرار: التشغيل بأمان عدة مرات
تكون دالة المسار المصممة جيدًا قابلة للتكرار: إذ ينتج عن تشغيلها مرتين على المدخل نفسه الناتج نفسه، من دون التسبب في آثار جانبية. تجنبوا التعديلات داخل المكان (df.drop(..., inplace=True))، واستخدموا دائمًا df.copy() في بداية الدوال التي تعدّل الأعمدة. ويمكن إعادة تشغيل الدوال القابلة للتكرار بعد حالات الفشل من دون إفساد بيانات الإخراج.
def add_revenue_flag(df, threshold=500):
# Use copy to avoid mutating the input
df = df.copy()
df['is_large_order'] = df['revenue'] >= threshold
return df
# Running twice gives the same result
df1 = add_revenue_flag(df_clean)
df2 = add_revenue_flag(df_clean)
assert df1.equals(df2), 'Function is not idempotent!'
print('Idempotency check passed.')تلميحات الأنواع للتوثيق الذاتي
أضيفوا تلميحات أنواع Python إلى تواقيع دوال التحويل لجعل العقد واضحًا: def transform(df: pd.DataFrame) -> pd.DataFrame. وتوثّق تلميحات الأنواع نفسها؛ فأي مطوّر يقرأ الدالة يعرف بالضبط ما تتوقعه وما تعيده من دون قراءة جسمها. كما تتيح أدوات التحليل الساكن مثل mypy والإكمال التلقائي في بيئات التطوير المتكاملة اكتشاف أخطاء الأنواع قبل وقت التشغيل.
from typing import List
def drop_null_rows(df: pd.DataFrame, required_cols: List[str]) -> pd.DataFrame:
return df.dropna(subset=required_cols)
def compute_revenue(df: pd.DataFrame) -> pd.DataFrame:
return df.assign(revenue=lambda d: d['quantity'] * d['unit_price'])
print('Type-annotated functions ready for production use.')توثيق كل خطوة باستخدام Docstrings
ينبغي أن تحتوي كل دالة تحويل على سلسلة توثيق من سطر واحد توضّح ما تفعله، والأعمدة التي تتطلبها، والأعمدة التي تضيفها أو تزيلها. وتجعل سلاسل التوثيق الجيدة الدالة قابلة للاكتشاف عبر help() وفي تلميحات أدوات بيئة التطوير المتكاملة. كما تعمل بوصفها مستندات مواصفات: فإذا ناقض تأكيد فاشل سلسلة التوثيق، كان ذلك خطأ؛ وإذا خالفت سلسلة التوثيق الشيفرة، كان ذلك خطأ في التوثيق.
def compute_revenue(df: pd.DataFrame) -> pd.DataFrame:
"""Add 'revenue' column as quantity * unit_price.
Requires: 'quantity' (numeric), 'unit_price' (numeric) columns.
Returns: df with new 'revenue' float column appended.
"""
return df.assign(revenue=lambda d: d['quantity'] * d['unit_price'])
help(compute_revenue)تشغيل المسار الكامل
نسّقوا عملية ETL الكاملة باستدعاء المراحل الثلاث بالتسلسل: الاستخراج، والتحويل، والتحميل. أضيفوا قياسًا للوقت حول كل مرحلة لمعرفة الموضع الذي يُستهلك فيه الوقت. والتقطوا الاستثناءات من كل مرحلة على حدة، حتى تحدد رسائل الخطأ المرحلة التي فشلت. وسجّلوا وقت بدء التشغيل الكامل ووقت انتهائه، وما إذا كان قد نجح أو فشل، لأغراض المراقبة.
import time
CONFIG = {
'input_path': 'orders.csv',
'output_path': 'orders_clean.parquet',
'required_cols': ['order_id', 'revenue']
}
t0 = time.time()
raw = extract(CONFIG)
clean = transform(raw, CONFIG)
load(clean, CONFIG)
print(f'Pipeline completed in {time.time()-t0:.1f}s')
print(f'Audit log: {audit_log}')تحقق سريع
اختبروا مدى فهمكم لمفاهيم تحليل البيانات التي تناولها هذا الدرس.
مراجعة الدرس
تعلمتم في هذا الدرس: هيكلة المسارات في صورة دوال ETL ذات مسؤولية واحدة، وجعل الدوال قابلة للاختبار وقابلة للتكرار وموثقة ذاتيًا باستخدام تلميحات الأنواع وسلاسل التوثيق، وتنسيق المسار الكامل مع قياس الوقت وتسجيلات التدقيق. نستكشف لاحقًا استخدام قواميس الإعدادات لتخصيص المسارات وإعادة استخدامها مع مجموعات بيانات مختلفة.
تعلم Python مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 30
- الدروس
- 120
الأسئلة الشائعة
هل درس «تنظيم خطوات التحويل في صورة دوال» مجاني؟
نعم — نص درس «تنظيم خطوات التحويل في صورة دوال» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Pandas & NumPy Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Pandas & NumPy Academy 4 دروس في المجموع.
ماذا ستتعلم في «تنظيم خطوات التحويل في صورة دوال»؟
قسّم دفتر الملاحظات إلى دوال للاستخراج والتحويل والتحميل، بحيث تقبل كل دالة DataFrame وتعيده لتسهيل الاختبار. تتمرن على Pandas & NumPy Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Pandas & NumPy Academy؟
لا تُشترط خبرة سابقة. Pandas & NumPy Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «تنظيم خطوات التحويل في صورة دوال»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Pandas & NumPy Academy هذا؟
نعم. كل درس في Pandas & NumPy Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- تنظيم خطوات التحويل في صورة دوال
- تخصيص مسارات المعالجة باستخدام قواميس الإعدادات
- اختبار خطوات مسار المعالجة بالتأكيدات
- جدولة عمليات مسار المعالجة وتسجيلها