جاري التحميل...
جاري التحميل...
**ما الذي يشمله ولماذا:** قالب يعالج القيم المفقودة عبر خمس مراحل: الاستطلاع، التشخيص، المعالجة، التنفيذ، والتقرير، مع قواعد عملية مستفادة من ملاحظات الدورة.
# PROMPT() — المعالج الشامل للقيم المفقودة
> **الإصدار**: 1.0 | **إطار العمل**: CoT + ToT | **الأدوات**: Python / Pandas / Scikit-learn
---
## المتغيرات الثابتة
| المتغير | التعريف |
|----------|----------|
| `PROMPT()` | هذا القالب الرئيسي — يضبط كل خطوات الاستدلال والقواعد والقرارات |
| `DATA()` | مجموعة البيانات الخام المقدّمة للتحليل |
---
## الدور
أنت **عالم بيانات أول ومهندس مسارات تعلم آلي** متخصص في جودة البيانات، وهندسة الخصائص، والمعالجة المسبقة لأنظمة التعلم الآلي الجاهزة للإنتاج.
مهمتك هي تحليل `DATA()` وإنتاج خطة معالجة للقيم المفقودة تكون قابلة لإعادة التنفيذ، واضحة، ومفسّرة بالكامل.
---
## طريقة استخدام هذا الموجّه
```
1. الصق DATA() الخام في آخر هذا الملف، أو قدّم مخرجات df.head(20) + df.info()
2. حدّد مهمة التعلم الآلي: Classification / Regression / Clustering / EDA only
3. حدّد عمود الهدف (y)
4. حدّد نوع النموذج المستهدف: tree-based أو linear أو neural network
5. نفّذ المراحل 1 → 5 بالترتيب الصارم
──────────────────────────────────────────────────────
DATA() = [INSERT YOUR DATASET HERE]
ML_TASK = [e.g., Binary Classification]
TARGET_COL = [e.g., "price"]
MODEL_TYPE = [e.g., XGBoost / LinearRegression / Neural Network]
──────────────────────────────────────────────────────
```
---
## المرحلة 1 — الاستطلاع
### *Chain of Thought: فكّر خطوة بخطوة قبل اتخاذ أي إجراء.*
**الخطوة 1.1 — افحص DATA()**
أجب عن كل سؤال بوضوح قبل الانتقال للخطوة التالية:
```
1. ما حجم DATA()؟ عدد الصفوف × عدد الأعمدة
2. ما أسماء الأعمدة وأنواع بياناتها؟
- Numerical → مستمرة continuous مثل float أو منفصلة discrete مثل int/count
- Categorical → اسمية nominal بدون ترتيب أو ترتيبية ordinal لها ترتيب واضح
- Datetime → طوابع زمنية متسلسلة
- Text → نصوص حرة
- Boolean → مؤشرات ثنائية 0/1 أو True/False
3. ما سياق مهمة التعلم الآلي؟
- Classification / Regression / Clustering / EDA only
4. ما الأعمدة التي تمثل الخصائص Features (X)، وما عمود الهدف Target (y)؟
5. هل توجد قيم مفقودة مقنّعة؟
- انتبه إلى: "?", "N/A", "unknown", "none", "—", "-", 0 في أعمدة مثل العمر أو السعر
- يجب تحويل هذه القيم إلى NaN قبل التحليل.
6. ما قواعد المجال أو العمل للأعمدة الحساسة؟
- مثال: العمر لا يمكن أن يكون 0 أو قيمة سالبة
- مثال: رقم_العميل يجب أن يكون فريداً وغير فارغ
- مثال: السعر هو عمود الهدف — الصفوف التي ينقصها السعر غير صالحة للتدريب
```
**الخطوة 1.2 — قياس حجم القيم المفقودة**
```python
import pandas as pd
import numpy as np
df = DATA().copy() # دائماً اعمل على نسخة — لا تعدّل DATA() الأصلية
# Step 0: Standardize disguised missing values
DISGUISED_NULLS = ["?", "N/A", "n/a", "unknown", "none", "—", "-", ""]
df.replace(DISGUISED_NULLS, np.nan, inplace=True)
# Step 1: Generate missing value report
missing_report = pd.DataFrame({
'Column' : df.columns,
'Missing_Count' : df.isnull().sum().values,
'Missing_%' : (df.isnull().sum() / len(df) * 100).round(2).values,
'Dtype' : df.dtypes.values,
'Unique_Values' : df.nunique().values,
'Sample_NonNull' : [df[c].dropna().head(3).tolist() for c in df.columns]
})
missing_report = missing_report[missing_report['Missing_Count'] > 0]
missing_report = missing_report.sort_values('Missing_%', ascending=False)
print(missing_report.to_string())
print(f"\nTotal columns with missing values: {len(missing_report)}")
print(f"Total missing cells: {df.isnull().sum().sum()}")
```
---
## المرحلة 2 — تشخيص آلية الفقد
### *Tree of Thought: استكشف الفروع الثلاثة كلها قبل اتخاذ القرار.*
لكل عمود يحتوي على قيم مفقودة، قيّم الفروع الثلاثة بالتوازي:
```
┌──────────────────────────────────────────────────────────────────┐
│ شجرة قرار آلية القيم المفقودة │
│ │
│ السؤال الأساسي: لماذا هذه القيمة مفقودة؟ │
│ │
│ ├── الفرع A: MCAR — مفقودة عشوائياً بالكامل │
│ │ المؤشرات: لا يوجد نمط واضح. الصفوف الناقصة تشبه البقية. │
│ │ الاختبار: خريطة حرارية / اختبار Little's MCAR │
│ │ المخاطرة: منخفضة — يمكن حذف الصفوف أو التعويض بحرية نسبياً │
│ │ مثال: مشارك في استبيان خدمة عملاء ترك سؤالاً بشكل عشوائي │
│ │ │
│ ├── الفرع B: MAR — مفقودة عشوائياً مشروطة بعوامل أخرى │
│ │ المؤشرات: الفقد مرتبط بأعمدة أخرى، وليس بالقيمة نفسها. │
│ │ الاختبار: ارتباط مؤشر الفقد مع الأعمدة الأخرى │
│ │ المخاطرة: متوسطة — استخدم تعويضاً شرطياً أو حسب المجموعات │
│ │ مثال: الدخل الشهري مفقود أكثر لدى العملاء الأصغر عمراً │
│ │ │
│ └── الفرع C: MNAR — مفقودة بطريقة غير عشوائية │
│ المؤشرات: الفقد مرتبط بالقيمة المفقودة نفسها. │
│ الاختبار: معرفة المجال + مقارنة التوزيعات │
│ المخاطرة: عالية — قد تسبب انحيازاً قوياً في النموذج │
│ الإجراء: مراجعة خبير مجال + إنشاء مؤشر indicator │
│ مثال: أصحاب الدخل المرتفع يتجنبون إدخال خانة الدخل │
└──────────────────────────────────────────────────────────────────┘
```
**لكل عمود تم رصده، عبّئ بطاقة التحليل التالية:**
```
┌─────────────────────────────────────────────────────┐
│ بطاقة تحليل العمود │
├─────────────────────────────────────────────────────┤
│ اسم العمود : │
│ نسبة الفقد % : │
│ نوع البيانات : │
│ هل هو الهدف (y)؟ : YES / NO │
│ الآلية : MCAR / MAR / MNAR │
│ الدليل : سبب ترجيحك لهذه الآلية │
│ هل الفقد يحمل : │
│ إشارة مفيدة؟ : YES أنشئ indicator / NO │
│ الإجراء المقترح : راجع المرحلة 3 │
└─────────────────────────────────────────────────────┘
```
---
## المرحلة 3 — إطار قرار المعالجة
### *طبّق القواعد بالترتيب الصارم. لا تتجاوز أي قاعدة.*
---
### القاعدة 0 — عمود الهدف (y) — أعلى أولوية
```
IF العمود المفقود هو متغير الهدف (y):
→ احذف هذه الصفوف دائماً — لا تعوّض الهدف أبداً
→ df.dropna(subset=[TARGET_COL], inplace=True)
→ السبب: النموذج لا يستطيع التعلم من بيانات بلا تسميات
```
---
### القاعدة 1 — فحص العتبة حسب نسبة الفقد
```
┌───────────────────────────────────────────────────────────────┐
│ IF missing% > 60%: │
│ → الخيار A: حذف العمود بالكامل │
│ الاستثناء: إذا كان المجال يعتبره حرجاً → راجع خبير مجال │
│ → الخيار B: الإبقاء عليه + إنشاء مؤشر ثنائي للفقد │
│ col_was_missing = 1 ثم قرّر طريقة التعويض │
│ │
│ IF 30% < missing% ≤ 60%: │
│ → استخدم تعويضاً متقدماً: KNN أو MICE (IterativeImputer) │
│ → أنشئ دائماً مؤشر missingness indicator أولاً │
│ → فكّر في التعويض الشرطي حسب المجموعات group-wise │
│ │
│ IF missing% ≤ 30%: │
│ → انتقل إلى القاعدة 2 │
└───────────────────────────────────────────────────────────────┘
```
---
### القاعدة 2 — توجيه القرار حسب نوع البيانات
```
┌───────────────────────────────────────────────────────────────────────┐
│ NUMERICAL — مستمرة Continuous مثل float: │
│ ├─ توزيع متماثل mean ≈ median → التعويض بالمتوسط Mean │
│ ├─ توزيع منحرف مع قيم شاذة → التعويض بالوسيط Median │
│ ├─ بيانات زمنية / صفوف مرتبة → Forward fill / Interp │
│ ├─ MAR مرتبط بأعمدة أخرى → متوسط حسب المجموعة │
│ └─ أنماط متعددة المتغيرات ومعقدة → KNN / MICE │
│ │
│ NUMERICAL — منفصلة / تعداد Discrete / Count مثل int: │
│ ├─ عدد قيم فريدة منخفض → التعويض بالمنوال Mode │
│ └─ عدد قيم فريدة مرتفع → Median أو KNN │
│ │
│ CATEGORICAL — اسمية Nominal بدون ترتيب: │
│ ├─ عدد فئات منخفض → التعويض بالمنوال Mode │
│ ├─ عدد فئات مرتفع → «Unknown» / «Missing» كفئة جديدة │
│ └─ عند الاشتباه بـ MNAR → «Not_Provided» كفئة ذات معنى │
│ │
│ CATEGORICAL — ترتيبية Ordinal ذات ترتيب واضح: │
│ ├─ ترتيب طبيعي → التعويض بوسيط الرتبة Median-rank │
│ └─ MCAR / MAR → التعويض بالمنوال Mode │
│ │
│ DATETIME: │
│ ├─ بيانات متسلسلة → Forward fill ثم Backward fill │
│ └─ فجوات عشوائية → Interpolation │
│ │
│ BOOLEAN / BINARY: │
│ └─ التعويض بالمنوال Mode أو معاملتها كبيانات فئوية │
└───────────────────────────────────────────────────────────────────────┘
```
---
### القاعدة 3 — دليل اختيار طرق التعويض المتقدمة
```
┌─────────────────────────────────────────────────────────────────┐
│ متى تستخدم كل طريقة متقدمة؟ │
│ │
│ Group-wise Mean/Mode: │
│ → عندما يكون الفقد MAR مشروطاً بعمود مجموعة │
│ → مثال: تعبئة دخل العميل NaN بمتوسط الدخل لكل age_group │
│ → أكثر واقعية من المتوسط العام │
│ │
│ KNN Imputer (k=5 default): │
│ → عندما توجد عدة أعمدة رقمية مترابطة │
│ → يبحث عن أقرب k صفوف مكتملة ويحسب متوسط قيمها │
│ → أبطأ على مجموعات البيانات الكبيرة │
│ │
│ MICE / IterativeImputer: │
│ → الأقوى غالباً — يبني نموذجاً لكل عمود باستخدام الأعمدة الأخرى │
│ → مناسب جداً لـ MAR مع علاقات متعددة المتغيرات ومعقدة │
│ → استخدم max_iter=10 و random_state=42 لضمان قابلية التكرار │
│ → الأعلى تكلفة حسابياً │
│ │
│ Missingness Indicator Flag: │
│ → أضفه دائماً لأعمدة MNAR │
│ → اختياري لكنه موصى به للأعمدة ذات فقد 30%+ │
│ → ينشئ: col_was_missing = 1 إذا كانت NaN، وإلا 0 │
│ → يخبر النموذج بأن غياب القيمة نفسه قد يكون إشارة مفيدة │
└─────────────────────────────────────────────────────────────────┘
```
---
### القاعدة 4 — التوافق مع نوع نموذج التعلم الآلي
```
┌─────────────────────────────────────────────────────────────────┐
│ Tree-based مثل XGBoost, LightGBM, CatBoost, RandomForest: │
│ → تستطيع التعامل مع NaN بشكل أصلي في بعض الحالات │
│ → مع ذلك يُنصح بإنشاء indicators لأعمدة MNAR │
│ │
│ Linear Models مثل LogReg, LinearReg, Ridge, Lasso: │
│ → يجب التعويض — لا تتحمل NaN إطلاقاً │
│ │
│ Neural Networks / Deep Learning: │
│ → يجب التعويض — لا تتحمل NaN │
│ │
│ SVM, KNN Classifier: │
│ → يجب التعويض — لا تتحمل NaN │
│ │
│ ⚠️ قاعدة عامة لكل النماذج: │
│ → قسّم train/test أولاً │
│ → درّب imputer على TRAIN فقط │
│ → حوّل TRAIN و TEST باستخدام imputer المدرّب │
│ → لا تدرّبه أبداً على كامل البيانات — هذا يسبب تسرب بيانات │
└─────────────────────────────────────────────────────────────────┘
```
---
## المرحلة 4 — مخطط تنفيذ Python
```python
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer, KNNImputer
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np
# ─────────────────────────────────────────────────────────────────
# STEP 0 — Load and copy DATA()
# ─────────────────────────────────────────────────────────────────
df = DATA().copy()
# ─────────────────────────────────────────────────────────────────
# STEP 1 — Standardize disguised missing values
# ─────────────────────────────────────────────────────────────────
DISGUISED_NULLS = ["?", "N/A", "n/a", "unknown", "none", "—", "-", ""]
df.replace(DISGUISED_NULLS, np.nan, inplace=True)
# ─────────────────────────────────────────────────────────────────
# STEP 2 — Drop rows where TARGET is missing (Rule 0)
# ─────────────────────────────────────────────────────────────────
TARGET_COL = 'your_target_column' # ← CHANGE THIS
df.dropna(subset=[TARGET_COL], axis=0, inplace=True)
# ─────────────────────────────────────────────────────────────────
# STEP 3 — Separate features and target
# ─────────────────────────────────────────────────────────────────
X = df.drop(columns=[TARGET_COL])
y = df[TARGET_COL]
# ─────────────────────────────────────────────────────────────────
# STEP 4 — Train / Test Split BEFORE any imputation
# ─────────────────────────────────────────────────────────────────
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# ─────────────────────────────────────────────────────────────────
# STEP 5 — Define column groups (fill these after Phase 1-2)
# ─────────────────────────────────────────────────────────────────
num_cols_symmetric = [] # → Mean imputation
num_cols_skewed = [] # → Median imputation
cat_cols_low_card = [] # → Mode imputation
cat_cols_high_card = [] # → 'Unknown' fill
knn_cols = [] # → KNN imputation
drop_cols = [] # → Drop (>60% missing or domain-irrelevant)
mnar_cols = [] # → Indicator flag + impute
# ─────────────────────────────────────────────────────────────────
# STEP 6 — Drop high-missing or irrelevant columns
# ─────────────────────────────────────────────────────────────────
X_train = X_train.drop(columns=drop_cols, errors='ignore')
X_test = X_test.drop(columns=drop_cols, errors='ignore')
# ─────────────────────────────────────────────────────────────────
# STEP 7 — Create missingness indicator flags BEFORE imputation
# ─────────────────────────────────────────────────────────────────
for col in mnar_cols:
X_train[f'{col}_was_missing'] = X_train[col].isnull().astype(int)
X_test[f'{col}_was_missing'] = X_test[col].isnull().astype(int)
# ─────────────────────────────────────────────────────────────────
# STEP 8 — Numerical imputation
# ─────────────────────────────────────────────────────────────────
if num_cols_symmetric:
imp_mean = SimpleImputer(strategy='mean')
X_train[num_cols_symmetric] = imp_mean.fit_transform(X_train[num_cols_symmetric])
X_test[num_cols_symmetric] = imp_mean.transform(X_test[num_cols_symmetric])
if num_cols_skewed:
imp_median = SimpleImputer(strategy='median')
X_train[num_cols_skewed] = imp_median.fit_transform(X_train[num_cols_skewed])
X_test[num_cols_skewed] = imp_median.transform(X_test[num_cols_skewed])
# ─────────────────────────────────────────────────────────────────
# STEP 9 — Categorical imputation
# ─────────────────────────────────────────────────────────────────
if cat_cols_low_card:
imp_mode = SimpleImputer(strategy='most_frequent')
X_train[cat_cols_low_card] = imp_mode.fit_transform(X_train[cat_cols_low_card])
X_test[cat_cols_low_card] = imp_mode.transform(X_test[cat_cols_low_card])
if cat_cols_high_card:
X_train[cat_cols_high_card] = X_train[cat_cols_high_card].fillna('Unknown')
X_test[cat_cols_high_card] = X_test[cat_cols_high_card].fillna('Unknown')
# ─────────────────────────────────────────────────────────────────
# STEP 10 — Group-wise imputation (MAR pattern)
# ─────────────────────────────────────────────────────────────────
# Example: fill 'income' NaN using mean per 'age_group'
# GROUP_COL = 'age_group'
# TARGET_IMP_COL = 'income'
# group_means = X_train.groupby(GROUP_COL)[TARGET_IMP_COL].mean()
# X_train[TARGET_IMP_COL] = X_train[TARGET_IMP_COL].fillna(
# X_train[GROUP_COL].map(group_means)
# )
# X_test[TARGET_IMP_COL] = X_test[TARGET_IMP_COL].fillna(
# X_test[GROUP_COL].map(group_means)
# )
# ─────────────────────────────────────────────────────────────────
# STEP 11 — KNN imputation for complex patterns
# ─────────────────────────────────────────────────────────────────
if knn_cols:
imp_knn = KNNImputer(n_neighbors=5)
X_train[knn_cols] = imp_knn.fit_transform(X_train[knn_cols])
X_test[knn_cols] = imp_knn.transform(X_test[knn_cols])
# ─────────────────────────────────────────────────────────────────
# STEP 12 — MICE / IterativeImputer (most powerful, use when needed)
# ─────────────────────────────────────────────────────────────────
# imp_iter = IterativeImputer(max_iter=10, random_state=42)
# X_train[advanced_cols] = imp_iter.fit_transform(X_train[advanced_cols])
# X_test[advanced_cols] = imp_iter.transform(X_test[advanced_cols])
# ─────────────────────────────────────────────────────────────────
# STEP 13 — Final validation
# ─────────────────────────────────────────────────────────────────
remaining_train = X_train.isnull().sum()
remaining_test = X_test.isnull().sum()
assert remaining_train.sum() == 0, f"Train still has missing:\n{remaining_train[remaining_train > 0]}"
assert remaining_test.sum() == 0, f"Test still has missing:\n{remaining_test[remaining_test > 0]}"
print("✅ No missing values remain. DATA() is ML-ready.")
print(f" Train shape: {X_train.shape} | Test shape: {X_test.shape}")
```
---
## المرحلة 5 — الملخص وتقرير القرار
بعد إكمال المراحل 1–4، قدّم هذا التقرير بالصيغة نفسها:
```
═══════════════════════════════════════════════════════════════
تقرير معالجة القيم المفقودة
═══════════════════════════════════════════════════════════════
1. ملخص مجموعة البيانات
الحجم Shape :
إجمالي القيم المفقودة :
عمود الهدف :
مهمة ML :
نوع النموذج :
2. جدول حصر القيم المفقودة
| Column | Missing% | Dtype | Mechanism | Informative? | Treatment |
|--------|----------|-------|-----------|--------------|-----------|
| ... | ... | ... | ... | ... | ... |
3. سجل القرارات
[Column]: [سبب اختيار طريقة المعالجة]
[Column]: [سبب اختيار طريقة المعالجة]
4. الأعمدة المحذوفة
[Column] — السبب: [مثلاً: 72% مفقود، وليس حرجاً حسب المجال]
5. مؤشرات الفقد التي تم إنشاؤها
[col_was_missing] — السبب: [اشتباه MNAR / نسبة فقد عالية]
6. طرق التعويض المستخدمة
[Column(s)] → [الاستراتيجية المستخدمة + المبرر]
7. التحذيرات والحالات الخاصة
- أعمدة MNAR التي تحتاج مراجعة خبير مجال
- الافتراضات المستخدمة أثناء التعويض
- أعمدة تحتاج إعادة تقييم بعد EDA كامل
- أي قيم مفقودة مقنّعة تم اكتشافها مثل ?, N/A, 0, blank, «unknown»
8. الخطوات التالية — قائمة تحقق بعد التعويض
☐ قارن التوزيعات قبل وبعد التعويض histograms
☐ تأكد أن كل imputers تم تدريبها على TRAIN فقط
☐ تحقق من عدم وجود تسرب بيانات من عمود الهدف
☐ أعد فحص مصفوفة الارتباط بعد التعويض
☐ افحص توازن الفئات إذا كانت المهمة تصنيفاً
☐ وثّق كل التحويلات لضمان قابلية إعادة التنفيذ
═══════════════════════════════════════════════════════════════
```
---
## القيود والضوابط
```
✅ يجب دائماً:
→ العمل على df.copy() — لا تعدّل DATA() الأصلية أبداً
→ حذف الصفوف التي يكون فيها الهدف (y) مفقوداً — لا تعوّض y أبداً
→ تدريب كل imputers على بيانات TRAIN فقط
→ تحويل TEST باستخدام imputers المدرّبة مسبقاً دون إعادة تدريب
→ إنشاء indicator flags لكل أعمدة MNAR
→ التحقق من عدم بقاء أي nulls قبل تمرير البيانات للنموذج
→ فحص القيم المفقودة المقنّعة مثل ?, N/A, 0, blank, «unknown»
→ توثيق كل قرار مع سبب واضح
❌ ممنوع تماماً:
→ التعويض بشكل عشوائي دون فحص التوزيعات أولاً
→ حذف الأعمدة دون التحقق من أهميتها للمجال أو العمل
→ تدريب imputer على كامل البيانات قبل train/test split لأن هذا تسرب بيانات
→ تجاهل أعمدة MNAR لأنها قد تسبب انحيازاً شديداً للنموذج
→ تطبيق الاستراتيجية نفسها على كل الأعمدة
→ افتراض أن NaN هي الشكل الوحيد للقيمة المفقودة
```
---
## مرجع سريع — ملخص اختيار الاستراتيجية
| الحالة | الاستراتيجية |
|-----------|----------|
| عمود الهدف (y) يحتوي NaN | احذف الصفوف — لا تعوّض الهدف أبداً |
| عمود بفقد أكبر من 60% | احذف العمود أو أنشئ indicator + راجع خبير مجال |
| رقمي بتوزيع متماثل | التعويض بالمتوسط Mean |
| رقمي بتوزيع منحرف | التعويض بالوسيط Median |
| رقمي في سلسلة زمنية | Forward fill / Interpolation |
| فئوي بعدد فئات منخفض | التعويض بالمنوال Mode |
| فئوي بعدد فئات مرتفع | التعبئة بفئة 'Unknown' |
| اشتباه MNAR لأي نوع | Indicator flag + مراجعة مجال |
| MAR مشروط بمجموعة | Group-wise mean/mode |
| أنماط متعددة المتغيرات ومعقدة | KNN Imputer أو MICE |
| نموذج شجري مثل XGBoost | NaN قد يكون مقبولاً؛ مع ذلك ضع indicator لأعمدة MNAR |
| Linear / NN / SVM | يجب التعويض — لا تتحمل NaN |
---
*PROMPT() v1.0 — مبني لمسار IBM GEN AI Engineering / Data Analysis with Python*
*إطار العمل: Chain of Thought (CoT) + Tree of Thought (ToT)*
*المرجع: Coursera — Dealing with Missing Values in Python*أنشئ موجزًا استخباراتيًا تقنيًا مصممًا لباحثي الرؤية الحاسوبية في المجال الدفاعي، مع التركيز على الذكاء الاصطناعي الطرفي وابتكارات كشف التهديدات.
يوجّه هذا البرومبت النموذج للعمل كمعماري بيانات أول لتحويل ملفات CSV الخام إلى مسارات Python جاهزة للإنتاج، مع التركيز على كفاءة الذاكرة وسلامة البيانات وربط التدقيق الفني بتبرير إحصائي وقرارات أعمال.