تطبيق SciPy وstatsmodels في بايثون عملياً: الكود والأوامر التي تهم حقاً
بايثون SciPy statsmodels: الأساسيات في مقال واحد — كود حقيقي، مخططات وخطوات ملموسة، مقتطفات من دورة مكونة من 37 درسًا.
لا توجد نظرية مطولة هنا: نفتح الطرفية ونمارس. إليك أساسيات Python SciPy statsmodels، مستخرجة مباشرة من دورة كاملة تضم 37 درسًا — مع كود حقيقي يمكنك نسخه ولصقه الآن.
- مقدمة وتثبيت
- تذكير NumPy لـ SciPy
- اكتشاف SciPy
- الإحصاء الوصفي باستخدام scipy.stats
- الاختبارات الإحصائية باستخدام SciPy
التنبؤ بالمستقبل باستخدام ARIMA
ما سنراه في هذا الدرس
ما هو ARIMA ببساطة؟
ARIMA هو خوارزمية تنبؤ. ينظر إلى القيم السابقة ويحاول استنتاج ما سيحدث في المستقبل.
الاسم الكامل هو Auto-Regressive Integrated Moving Average. اسم معقد، لكن المفهوم بسيط: يعتمد النموذج على القيم السابقة وأخطاء التنبؤ السابقة لتقدير القيمة التالية.
المعاملات الثلاثة لـ ARIMA: p، d، q
نكتب ARIMA(p, d, q). كل حرف له دور محدد.
| المعامل | المعنى | مثال بسيط |
|---|---|---|
| p | عدد القيم السابقة المستخدمة للتنبؤ | p=2: ننظر إلى الشهرين الأخيرين |
| d | عدد مرات تحويل السلسلة لتثبيتها | d=1: في معظم الحالات يكفي d=1 |
| q | عدد أخطاء الماضي المستخدمة لتصحيح التنبؤ | q=1: نأخذ بعين الاعتبار آخر خطأ |
بناء نموذج ARIMA خطوة بخطوة
نعود إلى سلسلة المبيعات الشهرية على مدى 4 سنوات. سنستخدم أول 38 شهرًا لتدريب النموذج، والـ 10 أشهر الأخيرة للتحقق من جودة التنبؤات.
import pandas as pd
import numpy as np
from statsmodels.tsa.arima.model import ARIMA
# --- إعادة إنشاء سلسلة المبيعات الشهرية ---
np.random.seed(42)
dates = pd.date_range(start="2020-01", periods=48, freq="ME")
tendance = np.arange(48) * 1.0
mois = dates.month
saisonnalite = 10 * np.sin(2 * np.pi * (mois - 3) / 12)
bruit = np.random.normal(0, 3, 48)
ventes = 100 + tendance + saisonnalite + bruit
serie = pd.Series(ventes, index=dates, name="Ventes")
# --- التقسيم: 38 شهرًا للتعلم، 10 أشهر للاختبار ---
train = serie.iloc[:38] # بيانات التدريب
test = serie.iloc[38:] # بيانات الاختبار (المستقبل المعروف)
print(f"Entrainement : {len(train)} mois")
print(f"Test : {len(test)} mois")# --- إنشاء وضبط النموذج ---
# order=(p, d, q) = (1, 1, 1) : الإعداد الأساسي
modele = ARIMA(train, order=(1, 1, 1))
resultat = modele.fit()
# عرض ملخص مختصر
print(f"AIC du modele : {resultat.aic:.2f}")
print("Modele ajuste avec succes !")إنشاء تنبؤ
الآن بعد تدريب النموذج، نطلب منه التنبؤ بالـ 10 أشهر القادمة.
# إنشاء تنبؤ لـ 10 أشهر
prevision = resultat.forecast(steps=10)
# مقارنة التنبؤ بالقيم الحقيقية
comparaison = pd.DataFrame({
"Reel" : test.values.round(1),
"Prevision": prevision.values.round(1),
"Erreur" : (test.values - prevision.values).round(1)
}, index=test.index)
print(comparaison)- Reel : المبيعات الحقيقية لهذه الأشهر (التي أخفيناها عن النموذج أثناء التدريب)
- Prevision : ما تنبأ به نموذج ARIMA
- Erreur : الفرق. خطأ قريب من 0 جيد. خطأ كبير يعني أن التنبؤ كان سيئًا.
قياس جودة التنبؤ
لمعرفة ما إذا كان نموذجنا يتنبأ جيدًا، نحسب متوسط الخطأ المطلق (MAE). هو ببساطة متوسط الأخطاء، دون مراعاة الإشارة (موجب أو سالب).
mae = np.abs(test.values - prevision.values).mean()
print(f"Erreur moyenne absolue (MAE) : {mae:.1f} unites")
print(f"Moyenne des ventes reelles : {test.mean():.1f} unites")
print(f"Erreur relative : {mae / test.mean() * 100:.1f}%")التنبؤ بالمستقبل بعد البيانات المتاحة
في الحياة الواقعية، لا تملك بيانات اختبار للمقارنة. تريد فقط التنبؤ بالأشهر القادمة.
أول سكريبت SciPy
الأهداف التعليمية
بنية سكريبت تحليل نموذجي
كل سكريبت تحليل بيانات في Python يتبع نمطًا مشابهًا. تعلم هذا النمط الآن سيساعدك في جميع الفصول اللاحقة.
المخطط العام
السيناريو: تحليل درجات دورة
أنت أستاذ. لديك درجات 20 طالبًا من 100. تريد فهم:
الخطوة 1: الاستيرادات
أول شيء تفعله في أي سكريبت هو استيراد المكتبات. إليك السبب في استخدام أسماء مستعارة:
import numpy as np # np أقصر في الكتابة من numpy from scipy import stats # نستورد فقط وحدة stats من SciPy import matplotlib.pyplot as plt # plt هو الاسم المستعار القياسي لرسم الرسوم البيانية
from scipy import stats وليس import scipy؟ — SciPy مقسم إلى وحدات فرعية. استيراد stats فقط أكثر كفاءة لأننا نحمل فقط ما نحتاجه. نكتب بعد ذلك stats.mean() بدلاً من scipy.stats.mean().الخطوة 2: إنشاء البيانات
notes = np.array([
72, 85, 91, 63, 78, 55, 88, 94, 70, 82,
66, 79, 87, 61, 90, 75, 83, 68, 77, 95
])
print("Nombre d'etudiants :", len(notes))
print("Notes :", notes)الخطوة 3: حساب الإحصاءات باستخدام scipy.stats
moyenne = np.mean(notes)
mediane = np.median(notes)
ecart_type = np.std(notes)
minimum = np.min(notes)
maximum = np.max(notes)
print(f"Moyenne : {moyenne:.2f}")
print(f"Mediane : {mediane:.2f}")
print(f"Ecart-type : {ecart_type:.2f}")
print(f"Minimum : {minimum}")
print(f"Maximum : {maximum}")الخطوة 4: استخدام scipy.stats للذهاب أبعد
NumPy يحسب الإحصاءات الأساسية. SciPy يذهب أبعد بإضافة مقاييس مثل الالتواء (skewness) والتفلطح (kurtosis)، اللذين يشيران إلى شكل التوزيع.
asymetrie = stats.skew(notes)
aplatissement = stats.kurtosis(notes)
description = stats.describe(notes)
print(f"Asymetrie (skewness) : {asymetrie:.4f}")
print(f"Aplatissement (kurt) : {aplatissement:.4f}")
print()
print("Description complete par scipy.stats.describe() :")
print(description)الخطوة 5: تفسير النتائج
| الإحصاء | القيمة | ما يعنيه |
|---|---|---|
| المتوسط | 77.95 | في المتوسط، حصل الطلاب على ما يقارب 78/100 |
| الوسيط | 78.50 | نصف الطلاب حصلوا على أقل من 78.5 والنصف الآخر أكثر |
| الانحراف المعياري | 11.32 | تختلف الدرجات بحوالي 11 نقاط حول المتوسط |
| الالتواء (-0.25) | طفيف | التوزيع شبه متماثل (تركيز طفيف نحو الدرجات العالية) |
| التفلطح (-0.88) | سالب | توزيع أكثر تسطحًا قليلاً من التوزيع الطبيعي (platykurtique) |
الخطوة 6: التصور (إضافي)
plt.figure(figsize=(8, 4))
plt.hist(notes, bins=8, color='steelblue', edgecolor='white', alpha=0.8)
plt.axvline(moyenne, color='red', linestyle='--', label=f'Moyenne ({moyenne:.1f})')
plt.axvline(mediane, color='orange', linestyle='-', label=f'Mediane ({mediane:.1f})')
plt.xlabel("Note sur 100")
plt.ylabel("Nombre d'etudiants")
plt.title("Distribution des notes de la classe")
plt.legend()
plt.tight_layout()
plt.show()ما يمكن فعله بمصفوفة NumPy
ما سنراه في هذا الدرس
قراءة قيمة محددة في مصفوفة
تخيل أن مصفوفتك صف من الخانات المرقمة. الخانة الأولى مرقمة 0، وليس 1. هذه اتفاقية في Python. الخانة الثانية هي 1، والثالثة 2، وهكذا.
يمكننا أيضًا العد من النهاية باستخدام أرقام سالبة. -1 يعطي العنصر الأخير، -2 قبل الأخير، إلخ.
import numpy as np # مصفوفة من 7 درجات حرارة أسبوعية temperatures = np.array([18.5, 22.1, 19.8, 25.3, 21.0, 17.2, 23.4]) # [0] [1] [2] [3] [4] [5] [6] print( temperatures[0] ) # 18.5 -> الاثنين (القيمة الأولى) print( temperatures[2] ) # 19.8 -> الأربعاء (القيمة الثالثة) print( temperatures[-1] ) # 23.4 -> الأحد (القيمة الأخيرة) print( temperatures[-2] ) # 17.2 -> السبت (قبل الأخيرة)
اختيار عدة قيم متتالية
إذا أردت أخذ جزء من المصفوفة، استخدم الترميز بداية:نهاية. انتبه: قيمة النهاية مستبعدة. إذا كتبت [1:4]، تحصل على الخانات 1، 2 و3، لكن ليس الخانة 4.
temperatures = np.array([18.5, 22.1, 19.8, 25.3, 21.0, 17.2, 23.4]) # الأيام الثلاثة الأولى (الاثنين، الثلاثاء، الأربعاء) print( temperatures[:3] ) # بداية محذوفة = من البداية # من الثلاثاء إلى الجمعة (الفهرس 1 إلى 4، 4 مستبعد) print( temperatures[1:4] ) # اليومان الأخيران print( temperatures[-2:] ) # نهاية محذوفة = حتى النهاية # يوم كل يومين (الاثنين، الأربعاء، الجمعة، الأحد) print( temperatures[::2] )
الاحتفاظ فقط بالقيم التي تحقق شرطًا
هذا من أقوى ميزات NumPy. يمكنك القول «أعطني فقط درجات الحرارة الأعلى من 21 درجة» ويقوم NumPy بالاختيار تلقائيًا.
إليك كيف يعمل في خطوتين:
temperatures = np.array([18.5, 22.1, 19.8, 25.3, 21.0, 17.2, 23.4])
# الخطوة 1: أي يوم تكون فيه درجة الحرارة أعلى من 21؟
masque = temperatures > 21
print("Masque :", masque)
# True حيث أكبر من 21، False خلاف ذلك
# الخطوة 2: الاحتفاظ فقط بهذه القيم
print("Jours > 21 degres :", temperatures[masque])
# يمكن أيضًا القيام بالخطوتين في سطر واحد:
print("Jours < 20 degres :", temperatures[temperatures < 20])إجراء حسابات رياضية على المصفوفة بأكملها
يقدم NumPy دوال رياضية تُطبق على كل عنصر في نفس الوقت. لا حاجة لحلقة. تكتب سطرًا واحدًا ويقوم NumPy بالحساب على جميع القيم.
data = np.array([4.0, 9.0, 16.0, 25.0])
# np.sqrt = الجذر التربيعي لكل قيمة
print("Racine carree :", np.sqrt(data))
# np.log = اللوغاريتم الطبيعي لكل قيمة
print("Logarithme :", np.round(np.log(data), 2))
# np.abs = القيمة المطلقة (يزيل الإشارة السالبة)
nombres = np.array([-3, 5, -7, 2])
print("Valeur absolue:", np.abs(nombres))حساب الإحصاءات على المصفوفة بأكملها
هذه الدوال تلخص المصفوفة في رقم واحد:
ventes = np.array([1200, 850, 1500, 970, 1100, 1350, 780])
print("Total de la semaine :", np.sum(ventes))
print("Moyenne journaliere :", np.mean(ventes).round(1))
print("Journee la plus haute :", np.max(ventes))
print("Journee la plus basse :", np.min(ventes))
# cumsum : المجموع التراكمي يومًا بيوم
print("Cumul jour par jour :", np.cumsum(ventes))تطبيق حساب على جميع القيم في نفس الوقت
في Python العادية، إذا أردت إضافة 10% إلى كل سعر في قائمة، تكتب حلقة. مع NumPy، لا تحتاج إلى ذلك. تكتب العملية مرة واحدة وتُطبق على جميع القيم. يُسمى هذا broadcasting.
يغطي هذا المقال المقتطفات الأكثر فائدة — الدورة الكاملة Python SciPy statsmodels (11 فصول، 37 درسًا، تمارين مصححة ومشروع نهائي) تأخذك إلى النهاية.
./acceder-au-cours-complet cours gratuit : Maîtriser Claude Codeالأسئلة الشائعة
كم من الوقت لتعلم Python SciPy statsmodels؟
هل هناك متطلبات سابقة؟
من أين نبدأ عمليًا؟
📬 هل تريد تلقي هذا النوع من الأدلة كل أسبوع؟ اشترك مجانًا — كود حقيقي، بدون كلام فارغ.