علوم البيانات: الرسم البياني في بايثون باستخدام مكتبة matplotlib

الرسم البياني مهم جدا في علم البيانات لأنه يساعد على تلخيص بيانات معقدة ومتداخلة برسوم بيانية توضيحية تعطينا فكرة عن توزع البيانات في مهمة تعرف ب Data exploration بالاضافة إلى توفير رسومات سهلة الفهم يمكن تقديمها لغير المختصين حول ما تمثله البيانات بشكل يمكن من خلاله استنتاج حقائق بشكل سريع مقارنة مع قيم رقمية ضمن جداول ضخمة، مثل نمو الأرباح خلال عام كامل مما يساعد على  اتخاذ قرارات بناءا على هذه الرسوم. سنعرض في هذه المقالة مقدمة إلى الرسم البياني في بايثون باستخدام مكتبة Matplotlib. 

لغة البرمجة بايثون
لغة البرمجة بايثون

مقدمة إلى مكتبة Matplotlib 

تعتبر مكتبة matplotlib من أهم مكتبات الرسم في بايثون والأكثر استخدام في علوم البيانات بشكل عام. 

تنقسم matplotlib إلى ثلاث طبقات رئيسية:

  • Backend Layer هذه الطبقة من ثلاث واجهات Interface أساسية مجردة FigureCanvas التي تمثل المنطقة التي سيتم رسم الشكل عليها، Renderer والتي تقوم بوصف كيف يتم رسم هذا الشكل و Event الذي يتعامل مع مدخلات المستخدم من الفأرة ولوحة المفاتيح.
  • Artist Layer تتألف هذه الطبقة من كائن واحد Artist الذي يقوم باستخدام الRenderer لرسم عناصر الشكل على لوحة الرسم Canvas, كل ما تراه على الشكل من عناوين وخطوط Lines و صور هو من كائن Object من نوع  Artist.

يوجد نوعين من كائنات Artist النوع الأول يدعى النوع الأساسي Primitive Type والذي يحوي عناصر مثل خطوط Line ومستطيلات ونصوص, النوع الثاني هو النوع المركب Composite يحوي أشكال Figure او محاور بيانية Axes.

  • Scripting Layer هذه الطبقة مخصصة لغير المختصين الذين لا تتوفر لديهم خبرة عالية في البرمجة, هذه الطبقة تتمثل بالواجهة Matplotlib.pyplot التي تقوم بأتمتة عمليات تعريف لوحة رسم Canvas وتعريف شكل Figure وربطهم مع بعض.

سنعرض فيمايلي أهم الخطوط البيانية في بايثون مع امثلة عن كل منها.

الخطوط البيانية Line Graph

الخطوط البيانية من أكثر الرسومات استخداما، وبالتعريف الخط البياني هوي خط رسومي يقوم بعرض معلومات على شكل سلسلة من البيانات كل منها يسمى نقطة بيانات Data points يتم عرضها على شكل علامات markers على لوح الرسم، ثم يتم وصل هذه العلامات باستخدام خطوط مستقيمة.

يستخدم الخط البياني لإيجاد العلاقة بين مجموعتين من البيانات يتم تمثيلهما على محورين X و Y. يساعد الخط البياني باكتشاف العلاقة بين هاتين المجموعتين بشكل مرئي سهل. 

مثلا اذا أردنا رسم خط بياني يقوم بعرض التابع الجيبي sin ضمن مجال معين، نقوم بالبداية بتعريف هذا المجال عن طريق مصفوفة x تأخذ قيم من الصفر إلى ، نستطيع الحصول على قيمة π من خلال استدعاء التابع np.pi. تمثل هذه المصفوفة البيانات على محور x. اما بالنسبة للبيانات على محور Y فهي قيمة التابع الجيبي sin  عند كل نقطة في X, لتوليد هذه المصفوفة يكفي استدعاء التابع sin وتمرير المصفوفة له حيث يعيد مصفوفة أخرى تحوي نفس عناصر x مطبّق عليها قيمة sin. 

أخيرا لرسم الخط البياني يكفي استدعاء التابع plot ضمن الواجهة pyplot التي قمنا باستيرادها باسم plt للسهولة وتمرير قيمتي x و y للتابع.

 نريد الأن وضع مسميات لمحور x ومحور y وعنوان للمخطط، يمكن القيام بذلك عن طريق التوابع xlabel, ylabel, title كما هو موضح بالمقطع البرمجي في الأسفل، وأخيرا لعرض الشكل يكفي استدعاء التابع show, ليصبح الكود البرمجي كمايلي:

import numpy as np
import matplotlib.pyplot as plt
 
x = np.arange(0,8*np.pi,0.1)
y= np.sin(x)
 
plt.plot(x,y)
plt.xlabel('Time')
plt.ylabel('Sin(Time)')
plt.title('Sine wave plot - Shamrablog.com')
plt.show()

عند تنفيذ المقطع البرمجي أعلاه، سنحصل على الشكل التالي:

نستطيع ايضا رسم خطين أو أكثر على  نفس لوح الرسم, يساعدنا ذلك بالمقارنة بين بيانات مختلفة ودراسة الفروق بينها، لنقوم مثلا برسم منحى بياني لموجة Cosine على  نفس البيانات, بالبداية نقوم بتوليد قيمة cosine للشعاع x باستخدام التابع cos الموجود في المكتبة numpy ووضع القيم الجديدة في y2، ثم نقوم بتمرير بيانات المنحني الثاني لتابع الرسم plot. بما أن لوح الرسم يحوي الأن خطين مختلفين, فيجب وضع دليل legend للقارئ لكي يستطيع التمييز بين الخطين, نستطيع القيام بذلك عن طريق استدعاء تابع legend وتمرير مصفوفة تحوي الوصف لكل خط رسم, سيقوم التابع باحترام الترتيب الذي قمنا فيه برسم الخطين وترتيب الدليل ليفترض ان العنصر الأول في المصفوفة هو وصف للرسم الأول, والعنصر الثاني هو للثاني. 

أيضا نحتاج إلى تحديد مكان ظهور الدليل على لوح الرسم. نستطيع القيام بذلك عن طريق ضبط البارامتر loc وتحديد المكان. 

نستطيع تحديد المكان أما عن طريق كتابته نصيا او عن طريق الكود الخاص به كرقم, على سبيل المثال لعرض دليل الرسم في الزاوية العليا اليمنى نستطيع تمرير النص ‘upper right’ او الكود المرافق لها 1,  الخيارات الممكنة لهذا البارامتر متوفرة على الرابط التالي 

ليصبح الكود البرمجي الكامل لرسم منحنيي sin او cos للقيم من 0 إلى 8pi كمايلي:

import numpy as np
import matplotlib.pyplot as plt
 
x = np.arange(0,8*np.pi,0.1)
y= np.sin(x)
y2= np.cos(x)
 
plt.plot(x,y,x,y2)
plt.xlabel('Time')
plt.ylabel('Sin(Time), Cos(Time)')
plt.legend(['sin(Time)','cos(Time)'],loc='upper right')
plt.title('sin(Time) and cos(Time) from 0 to 8pi -Shamrablog.com')
plt.show()

عند تنفيذ المقطع البرمجي في الأعلى، سنحصل على الشكل التالي:


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

تاتي كلمة histogram من دمج كلمتين Histos و Gramma أي رسم او كتابة على شكل مستقيمات. لايوجد مصطلح عربي واضح لل Histogram غير مدرج تكراري او احيانا يتم الإشارة إليه ب هيستوجرام, لرسم مدرج تكراري نتحاج إلى جدول يتالف من عمودين، العمود الأول يمثل الفئة او القيمة على محور X غالبا ما نشير إليه ب Bins  والعمود الثاني يمثل عدد التكرارات على محور Y او Frequency.

في المثال التالي سنقوم برسم مدرج تكراري باستخدام مكتبة pyplot لمجموعة من الأرقام العشوائية (10000 رقم).

لاحظ ان التوزع الطبيعي للأعداد المتولدة له متوسط mean مساوي للصفر وسيغما = ١ يمكن استدلال هذه الأرقام بسهولة عند النظر إلى المدرج التكراري المولّد.

import matplotlib.pyplot as plt
import numpy as np

#Generate an array of 10000 random numbers
x = np.random.randn(10000)
plt.hist(x,100)
plt.title(r'Normal Distribution with $\mu=0, \sigma=1$')
plt.show()

لنحصل على الشكل الأتي:

المخططات الشريطية Bar 

تستخدم المخططات الشريطية Bar لرسم مجموعة من المستطيلات طول كل مستطيل يتناسب مع القيمة التي يمثلها في البيانات. تستخدم هذه الخطوط للمقارنة بين قيمتين أو أكثر من القيم تم تسجيلها حسب زمن معين أو ضمن ظروف وأماكن مختلفة. 

يمكن أن تكون المخططات الشريطة أفقية أو عمودية ويكون بالعادة لكل شريط لون مختلف عن الأخر لسهولة قراءة المخطط.

تدعم مكتبة matplotlib رسم المخططات الشريطية عبر تابع bar يقبل التابع البارامترات التالية:

  • X وهو عبارة عن مصفوفة من الأرقام تمثل موضع البيانات على محور X.
  • Height مصفوفة تمثل قيم أو ارتفاع كل مخطط  (قيمته على محور Y) يجب أن تكون هذه المصفوفة بنفس طول المصفوفة X
  • Width مصفوفة تمثل عرض كل مخطط.
  • Bottom مصفوفة خيارية تمثل احداثيات كل مخطط (من اسفل وليس من أعلى – اي لا تمثل طوله ولكن تمثل نقطة بدايته على محور Y) بشكل افتراضي تكون قيمتها صفر او None
  • Align أي تمركز الاشرطة على محور X لها قيمة افتراضية center يمكن ان تكون ايضا edge اي تكون الأشرطة
  • Color لون الخطوط أما ان يكون لون واحد للجميع او مصفوفة يتم تحديد لون كل شريط بشكل منفصل.

على سبيل المثال، نريد نرسم مخطط شريطي يوضح قيمة المبيعات لشركة ما في عدة مدن سورية. نقوم بالبداية بتعريف مصفوفة تحوي أسماء المدن names، ثم نقوم بتعريف مصفوفة أخرى sales  تحوي قيمة المبيعات في كل مدينة، يجب ان ننتبه ان ترتيب المبيعات في المصفوفة sales يجب ان يطابق ترتيب المبيعات في المصفوفة names، مثلا قيمة المبيعات في مدينة اللاذقية هي ١٠ (الواحدة هي مليون ليرة سورية لتسهيل قراءة الأرقام على المخطط سنكتفي بوضع ١٠).

كل مدينة سنقوم برسم شريط خاص بها على المخطط، لتجنب تراكم ال bars فوق بعضهم, يجب تحديد موقع لها على المحور x يختلف عن الأخر، نستطيع كتابة الاحداثيات بشكل يدوي ضمن مصفوفة، ولكن في حال كان عدد القيم كبير سيصبح ذلك غير  فعال، لذلك يوجد طريقة اسهل بتوليد مصفوفة باستخدام التابع arange عدد عناصرها من طول مصفوفة المدن، نحصل على طول مصفوفة المدن (او عدد المدن) باستخدام التابع len (اختصار ل length).

ليصبح الكود البرمجي كمايلي:

import matplotlib.pyplot as plt
import numpy as np

names = ['Latakia','Damascus','Aleppo','Homs']
#Sales vector, represents the height of the bars
sales = [10,15,12,8]
#represents the position of the bars

y_pos = np.arange(len(names))

plt.bar(y_pos, sales, color=['r','b','g','y'])
plt.xticks(y_pos,names)

plt.title('Sales in four Syrian cities in Million SP')
plt.xlabel('City')
plt.ylabel('Sales')
plt.show()

عند تنفيذ الكود أعلاه سنحصل على المخطط التالي:

قمت في هذه المقالة بتقديم لمحة سريعة عن مكتبة matplotlib للرسم البياني في بايثون، الغرض من هذه المقالة هو تشجيع كل باحث او عالم بيانات او حتى غير مختص بالبرمجة ولم يستخدم هذه المكتبة قبل، للتعرف عليها والبدء باستخدامها نظرا لسهولتها والمزايا الكبيرة التي تدعمها.

أنصح بتجربة المقاطع البرمجية في الأعلى أولا، ثم استبدال البيانات ببيانات حقيقية من بحثك او عملك، في حال واجهتك مشكلة او لديك اقتراح او ملاحظة، لا تتردد بطرح أي سؤال في التعليقات.

سأقوم بالمستقبل بتقديم أمثلة اخرى وشرح لمزايا اخرى لهذه المكتبة.