0%
Matplotlib: إنشاء تصورات بيانية احترافية في Python

Matplotlib: إنشاء تصورات بيانية احترافية في Python

دليل شامل إلى Matplotlib لإنشاء المنحنيات ومخططات الانتشار والأعمدة والمدرجات التكرارية في Python باستخدام الواجهة الكائنية، وsubplots، والتصدير.

I

InSkillCoach

· دقيقة

Matplotlib: إنشاء تصورات بيانية احترافية في Python

تُعدّ Matplotlib مكتبة التصور البياني التاريخية التي لا غنى عنها في منظومة Python. فهي تتيح إنتاج جميع أنواع الرسوم البيانية الكلاسيكية (المنحنيات، ومخططات الانتشار، والأعمدة، والمدرجات التكرارية) مع تحكّم كامل في كل عنصر من عناصر الشكل، كما تتيح تصدير النتيجة بصيغ مناسبة للويب وللطباعة على حد سواء. يعرض هذا الدليل بنية الشكل البياني، والواجهة الكائنية الموصى بها، وأهم أنواع الرسوم، وتقنيات التخصيص التي تصنع الفرق بين رسم بياني مسودّة وتصور بياني احترافي.

بنية الشكل البياني: Figure وAxes

يكفي فهم كائنين لفتح مفاتيح المكتبة كلها:

  • Figure هو الحاوية العامة: «ورقة الرسم» التي تحمل كل ما عداها (الحجم، والدقة، والخلفية).
  • Axes تمثّل منطقة رسم: نظام محاور له تدريجاته وتسمياته ومنحنياته. يمكن أن يحتوي الشكل على Axes واحد أو أكثر.

داخل Axes نجد المحورين x وy (xaxis وyaxis)، والتدريجات (ticks)، والتسميات (labels)، والعنوان، ومفتاح الرسم (legend)، والعناصر المرسومة (artists) من خطوط ونقاط وأعمدة.

import matplotlib.pyplot as plt
import numpy as np

# Une figure contenant un seul Axes
fig, ax = plt.subplots(figsize=(8, 5))

print(type(fig))   # <class 'matplotlib.figure.Figure'>
print(type(ax))    # <class 'matplotlib.axes._axes.Axes'>

واجهة pyplot مقابل الواجهة الكائنية

تقدّم Matplotlib أسلوبين للكتابة:

x = np.linspace(0, 2 * np.pi, 100)

# Style pyplot (à la MATLAB) : un état global implicite
plt.plot(x, np.sin(x))
plt.title("Sinus")
plt.xlabel("x")
plt.show()

# Style orienté objet : on manipule explicitement fig et ax
fig, ax = plt.subplots()
ax.plot(x, np.sin(x))
ax.set_title("Sinus")
ax.set_xlabel("x")
plt.show()

التوصية: اعتمدوا الواجهة الكائنية. أسلوب pyplot مقبول للرسم السريع في سطر واحد، لكن بمجرد أن يحتوي الشكل على عدة رسوم فرعية أو يُبنى داخل دالة، تصبح الحالة العامة في pyplot مصدرًا للأخطاء. فالواجهة الكائنية تجعل واضحًا أي Axes يتلقى أي أمر، وهي الأسلوب المستخدم في الوثائق الرسمية الحديثة. وتعتمدها جميع أمثلة هذا الدليل.

المنحنيات باستخدام plot

x = np.linspace(0, 10, 200)

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label="sin(x)", color="tab:blue", linewidth=2)
ax.plot(x, np.cos(x), label="cos(x)", color="tab:orange",
        linestyle="--", linewidth=2)
ax.plot(x[::20], np.sin(x[::20]), "o", color="tab:blue",
        markersize=6, label="points mesurés")

ax.set_title("Fonctions trigonométriques")
ax.set_xlabel("x (radians)")
ax.set_ylabel("Amplitude")
ax.legend()
ax.grid(True, alpha=0.3)
plt.show()

أنماط الخطوط الشائعة: "-" (متصل)، و"--" (شرطات)، و":" (نقاط)، و"-." (مختلط). والعلامات: "o" (دائرة)، و"s" (مربع)، و"^" (مثلث)، و"+"، و"x".

مخططات الانتشار باستخدام scatter

تتيح scatter تغيير حجم كل نقطة ولونها، ما يسمح بترميز ما يصل إلى أربعة متغيرات في رسم بياني واحد.

rng = np.random.default_rng(42)
x = rng.random(80)
y = 2 * x + rng.normal(0, 0.2, 80)
tailles = rng.integers(20, 200, 80)
couleurs = y - 2 * x                     # écart au modèle

fig, ax = plt.subplots(figsize=(8, 5))
nuage = ax.scatter(x, y, s=tailles, c=couleurs, cmap="viridis",
                   alpha=0.7, edgecolors="black", linewidths=0.5)

fig.colorbar(nuage, ax=ax, label="Résidu")
ax.set_title("Nuage de points avec taille et couleur variables")
ax.set_xlabel("x")
ax.set_ylabel("y")
plt.show()

المخططات الشريطية (الأعمدة)

langages = ["Python", "SQL", "JavaScript", "Rust"]
popularite = [48, 35, 30, 12]

fig, ax = plt.subplots(figsize=(8, 5))
barres = ax.bar(langages, popularite, color="tab:blue", edgecolor="black")

# Étiqueter chaque barre avec sa valeur
ax.bar_label(barres, fmt="%d %%")

ax.set_title("Popularité des langages (exemple)")
ax.set_ylabel("Part des répondants (%)")
ax.set_ylim(0, 55)
plt.show()

# Barres horizontales : plus lisibles quand les catégories ont des noms longs
fig, ax = plt.subplots(figsize=(8, 4))
ax.barh(langages, popularite, color="tab:green")
ax.set_xlabel("Part des répondants (%)")
plt.show()

للحصول على أعمدة مجمّعة، أزيحوا المواضع بإزاحة عددية:

positions = np.arange(len(langages))
largeur = 0.35
annee_1 = [45, 33, 32, 8]
annee_2 = [48, 35, 30, 12]

fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(positions - largeur / 2, annee_1, largeur, label="2025")
ax.bar(positions + largeur / 2, annee_2, largeur, label="2026")
ax.set_xticks(positions)
ax.set_xticklabels(langages)
ax.legend()
plt.show()

المدرجات التكرارية

يعرض المدرج التكراري توزيع متغير مستمر.

rng = np.random.default_rng(0)
donnees = rng.normal(loc=170, scale=8, size=1000)   # tailles simulées

fig, ax = plt.subplots(figsize=(8, 5))
valeurs, bords, patches = ax.hist(donnees, bins=30, color="tab:blue",
                                  edgecolor="white", alpha=0.85)

ax.axvline(donnees.mean(), color="red", linestyle="--",
           label=f"Moyenne = {donnees.mean():.1f} cm")
ax.set_title("Distribution des tailles")
ax.set_xlabel("Taille (cm)")
ax.set_ylabel("Effectif")
ax.legend()
plt.show()

# density=True normalise pour comparer à une densité de probabilité
# bins accepte un entier, une liste de bords, ou "auto"

المخططات الدائرية

استخدموها باعتدال (إذا زادت الفئات على 5 ففضّلوا الأعمدة الأفقية):

parts = [45, 25, 20, 10]
etiquettes = ["Cloud", "Data", "Web", "Autres"]

fig, ax = plt.subplots(figsize=(6, 6))
ax.pie(parts, labels=etiquettes, autopct="%1.1f%%",
       startangle=90, explode=(0.05, 0, 0, 0),
       colors=["tab:blue", "tab:orange", "tab:green", "tab:gray"])
ax.set_title("Répartition du chiffre d'affaires")
plt.show()
# autopct affiche les pourcentages, explode détache la première part

Subplots وشبكات الرسوم البيانية

تنشئ plt.subplots(lignes, colonnes) شبكة من كائنات Axes في استدعاء واحد.

x = np.linspace(0, 2 * np.pi, 100)

fig, axes = plt.subplots(2, 2, figsize=(10, 8))
# axes est un tableau NumPy 2D d'objets Axes

axes[0, 0].plot(x, np.sin(x))
axes[0, 0].set_title("sin(x)")

axes[0, 1].plot(x, np.cos(x), color="tab:orange")
axes[0, 1].set_title("cos(x)")

axes[1, 0].plot(x, np.sin(2 * x), color="tab:green")
axes[1, 0].set_title("sin(2x)")

axes[1, 1].plot(x, np.exp(-x) * np.sin(5 * x), color="tab:red")
axes[1, 1].set_title("Oscillation amortie")

fig.suptitle("Grille de quatre graphiques", fontsize=14)
fig.tight_layout()      # ajuste les espacements pour éviter les chevauchements
plt.show()

# Axes partagés : pratique pour comparer des séries
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(8, 6))

وللتخطيطات غير المنتظمة (رسم عريض في الأعلى ورسمان صغيران في الأسفل)، استكشفوا fig.add_gridspec أو plt.subplot_mosaic.

التخصيص: العناوين ومفاتيح الرسم والألوان والأنماط

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x), label="signal")

# Titres et étiquettes avec contrôle typographique
ax.set_title("Titre principal", fontsize=14, fontweight="bold")
ax.set_xlabel("Temps (s)", fontsize=11)
ax.set_ylabel("Amplitude (V)", fontsize=11)

# Légende : position et habillage
ax.legend(loc="upper right", frameon=True, shadow=False)

# Limites et graduations
ax.set_xlim(0, 2 * np.pi)
ax.set_xticks([0, np.pi, 2 * np.pi])
ax.set_xticklabels(["0", "π", "2π"])

# Grille discrète
ax.grid(True, linestyle=":", alpha=0.5)

# Supprimer les bordures superflues (style épuré)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
plt.show()

تتيح أوراق الأنماط تغيير المظهر العام بسطر واحد:

print(plt.style.available[:5])
# ['Solarize_Light2', '_classic_test_patch', '_mpl-gallery', '_mpl-gallery-nogrid', 'bmh']

plt.style.use("seaborn-v0_8-whitegrid")   # style sobre adapté aux rapports

# Ou localement, sans modifier l'état global :
with plt.style.context("ggplot"):
    fig, ax = plt.subplots()
    ax.plot(x, np.sin(x))

بالنسبة إلى الألوان، فضّلوا لوحة tab: المسمّاة (tab:blue وtab:orange وغيرهما): فهي مصمَّمة لتكون متمايزة ومقروءة، وحتى لمن يعانون عمى الألوان إلى حد كبير.

التعليقات التوضيحية

x = np.linspace(0, 10, 200)
y = np.exp(-x / 3) * np.sin(2 * x)

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, y)

# Texte simple positionné en coordonnées des données
ax.text(6, 0.4, "Zone amortie", fontsize=11, color="gray")

# Annotation avec flèche vers un point précis
i_max = y.argmax()
ax.annotate(f"Maximum ({x[i_max]:.2f}, {y[i_max]:.2f})",
            xy=(x[i_max], y[i_max]),          # pointe de la flèche
            xytext=(3, 0.8),                  # position du texte
            arrowprops=dict(arrowstyle="->", color="black"))

# Lignes de repère
ax.axhline(0, color="black", linewidth=0.8)
ax.axvline(x[i_max], color="red", linestyle=":", alpha=0.6)
plt.show()

المقاييس اللوغاريتمية

لا غنى عنها متى غطّت البيانات عدة رتب من الحجم.

n = np.logspace(1, 6, 50)          # de 10 à 1 000 000
temps_lineaire = n * 1e-6
temps_quadratique = n ** 2 * 1e-9

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(n, temps_lineaire, label="O(n)")
ax.plot(n, temps_quadratique, label="O(n²)")

ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlabel("Taille de l'entrée n")
ax.set_ylabel("Temps (s)")
ax.set_title("Complexités comparées (échelle log-log)")
ax.legend()
ax.grid(True, which="both", alpha=0.3)   # grille sur graduations majeures et mineures
plt.show()

# Raccourcis : ax.semilogy(...), ax.semilogx(...), ax.loglog(...)

الحفظ باستخدام savefig

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(x, np.sin(x))

# PNG haute résolution pour le web ou les slides
fig.savefig("graphique.png", dpi=200, bbox_inches="tight")

# SVG ou PDF : vectoriels, parfaits pour l'impression et les articles
fig.savefig("graphique.svg", bbox_inches="tight")
fig.savefig("graphique.pdf", bbox_inches="tight")

# Fond transparent pour intégration dans des slides
fig.savefig("graphique_transparent.png", dpi=200, transparent=True)

هناك معاملان ينبغي تذكّرهما: dpi يتحكم في دقة الصيغ النقطية (من 150 إلى 300 للحصول على عرض واضح)، وbbox_inches="tight" يزيل الهوامش البيضاء الزائدة. استدعوا savefig قبل plt.show()، لأن show قد يُفرغ الشكل في بعض البيئات.

التكامل مع Pandas

تتيح DataFrames طريقة .plot تفوّض الرسم إلى Matplotlib وتعيد كائن Axes، يمكنكم بعدها تخصيصه بالطريقة المعتادة.

import pandas as pd

df = pd.DataFrame({
    "mois": pd.date_range("2026-01-01", periods=6, freq="MS"),
    "ventes": [120, 135, 150, 145, 170, 190],
    "couts": [100, 110, 118, 120, 130, 140],
}).set_index("mois")

# Le DataFrame trace directement sur un Axes existant
fig, ax = plt.subplots(figsize=(8, 5))
df.plot(ax=ax, marker="o")

ax.set_title("Ventes et coûts mensuels")
ax.set_ylabel("k€")
ax.legend(["Ventes", "Coûts"])
plt.show()

# Autres raccourcis : df.plot.bar(), df.plot.hist(), df.plot.scatter(x=..., y=...)

كلمة عن Seaborn

Seaborn طبقة إضافية فوق Matplotlib موجَّهة نحو الإحصاء: فهي تنتج في سطر واحد رسومًا كانت ستتطلب عشرات الأسطر في Matplotlib الخالصة (مخططات الصندوق حسب الفئة، ومصفوفات الارتباط، والانحدارات مع فواصل الثقة).

import seaborn as sns

tips = sns.load_dataset("tips")

fig, ax = plt.subplots(figsize=(8, 5))
sns.boxplot(data=tips, x="day", y="total_bill", hue="sex", ax=ax)
ax.set_title("Distribution des additions par jour")
plt.show()

وبما أن Seaborn تعيد كائنات Matplotlib، يظل كل ما تعلمتموه في هذا الدليل (Axes والعناوين وsavefig) قابلًا للتطبيق. وعمليًا، يستخدم كثير من المحللين Seaborn للاستكشاف السريع وMatplotlib الخالصة للأشكال النهائية ذات التحكم الدقيق.

أفضل الممارسات

  • استخدموا الواجهة الكائنية (fig, ax = plt.subplots()) في كل مكان: فهي صريحة وقابلة للتركيب وتجنّبكم أخطاء الحالة العامة.
  • ضعوا تسميات لكل شيء: الرسم البياني الذي بلا عنوان ولا وحدات على المحاور ولا مفتاح رسم لا يمكن الاستفادة منه خارج سياق إنشائه.
  • استدعوا fig.tight_layout() (أو أنشئوا الشكل باستخدام layout="constrained") لتجنّب تداخل النصوص.
  • اختاروا نوع الرسم المناسب: منحنى للتطور، وأعمدة للفئات، ومدرج تكراري للتوزيع، ومخطط انتشار للعلاقة.
  • صدّروا بصيغة متجهية (SVG وPDF) للطباعة والمستندات، وبصيغة PNG مع dpi>=150 للويب.
  • قلّلوا الحمل البصري: احذفوا الحدود غير الضرورية، وخفّفوا الشبكة باستخدام alpha، واحتفظوا بالألوان الزاهية للمعلومة المهمة.
  • ثبّتوا البذرة العشوائية في الأمثلة والعروض التوضيحية للحصول على أشكال قابلة للتكرار.

الخلاصة

تقوم Matplotlib على نموذج بسيط، هو Figure الذي يحتوي على Axes، وتتيح الواجهة الكائنية التعامل معه بدقة. وبأنواع الرسوم القليلة المعروضة هنا (المنحنيات ومخططات الانتشار والأعمدة والمدرجات التكرارية)، وsubplots وأدوات التخصيص، تغطّون ما يقارب كل احتياجات التصور البياني في تحليل البيانات. ويسهّل التكامل الأصلي مع Pandas الانتقال من البيانات إلى الرسم، بينما تسرّع Seaborn الاستكشاف الإحصائي. وللتعمق أكثر، يُعدّ المعرض الرسمي لـ Matplotlib مرجعًا قيّمًا: إذ يرافق كل شكل فيه شيفرته المصدرية الكاملة.

InSkillCoach

نبذة عن InSkillCoach

خبير في التدريب والتقنيات

مدرّب متخصص في التقنيات المتقدمة والذكاء الاصطناعي، تدعمه شركة GNeurone Inc.

الشهادات:

  • AWS Certified Solutions Architect – Professional
  • شهادات Google Cloud
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
1.8k
303

التعليقات

التعليقات مدعومة عبر GitHub Discussions

سجّل الدخول باستخدام GitHub للمشاركة في النقاش

تم نسخ الرابط!