مكتبة Numpy - الخطوة الأولى في علم البيانات بلغة البايثون

مكتبة Numpy – الخطوة الأولى في علم البيانات بلغة البايثون

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

  • تثبيت مكتبة Numpy.
  • إنشاء مصفوفة Numpy.
  • إستيراد وتصدير البيانات من/إلى المصفوفة إلى/من ملفات خارجية.
  • التعرف على خصائص المصفوفات في مكتبة Numpy.
  • إجراء العمليات الرياضية على المصفوفات.
  • إجراء عمليات Subsetting, Slicing, Indexing.
  • تغيير شكل المصفوفات.
  • الحصول على مساعدة من دوال متخصصة في مكتبة Numpy.
  • طَرْقْ المصفوفة, وإجراء عمليات الإضافة والحذف.

سنقدم لكم أيضًا في نهاية المقال بعض الروابط الاضافية التي ستساعدكم في تعلم مكتبة Numpy

مصفوفة Numpy

يوجد بعض النقاط التي تتشابه فيها مصفوفة Numpy مع المصفوفة العادية List  في البايثون، ولكنهما يختلفان في نقاط أخرى عديدة.

تُعد مصفوفة Numpy أحد أهم تراكيب البيانات في مكتبة Numpy. سُميت بهذا الإسم إختصارا للمصطلح Numerical Python، ومن المصطلح نُدرك أن هذه المكتبة هي مكتبة متخصصة في الحوسبة العلمية بلغة البايثون، وتحتوي على تشكيلة متنوعة من الأدوات والتقنيات التي من الممكن ان تُستخدم لحل مشاكل رياضية في مجالي العلوم والهندسة. أحد أهم هذه الأدوات في المكتبة هي المصفوفة ذات الأبعاد المتعددة والكفاءة الفائقة High Performance Multidimensional Array، والتي نستطيع أن نُنفذ من خلالها الكثير من الدوال الرياضية والعمليات الحسابية والعمل على حل العديد من المشاكل.

تثبيت مكتبة Numpy

تثبيت مكتبة Numpy

قبل ان نبدأ بالعمل مع المصفوفات في مكتبة Numpy، لابد علينا أن نتأكد من وجودها ضمن المكتبات المثبتة في بيئة عمل البايثون. يوجد لدينا عدة خيارات نستطيع إختيار أحدَها لتثبيت المكتبة وهي كالتالي:

أولا: بإستخدام Python Wheels

نتبع الخطوات التالية:

  • نتأكد أن بيئة عمل البايثون مثبتة على الجهاز الذي نعمل عليه، وإن لم تكن كذلك يُمكننا تثبيت البايثون من هنا.
  • نتأكد من عمل أداة pip وأن البايثون مضافة في متغير PATH environment.
  • في شاشة cmd ننفذ أمر pip install –upgrade pip لعمل تحديث ل pip.
  • من هنا نحصل على ملف wheel الذي يُناسب نسخة البايثون الموجودة لدينا.
  • ننفذ الأمر التالي pip install numpy_wheel_file
  • من خلال مُفسر أوامر البايثون نستورد المكتبة import numpy وفي حال لم تظهر أي رسالة خطأ، تكون عملية تثبيت المكتبة تمت بنجاح.

ثانيا: بإستخدام توزيعة بايثون Anaconda

تناولنا في بايثونات وبشكل سريع توزيعة أناكوندا في مقال سابق. للحصول على مكتبة Numpy بشكل سهل وسريع يُمكننا تثبيت توزيعة Anaconda، وبذلك نختصر على أنفسنا وقت وجهد.

إنشاء مصفوفة Numpy

مصفوفة البايثون Numpy

بعد أن أتممنا تثبيت البايثون ومكتبة Numpy، فإنه قد حان وقت العمل.

حتى يتسنى لنا البدء بإنشاء المصفوفة، ينبغي إستيراد المكتبة في شيفرة البايثون الذي نكتبها، او في جلسة العمل على مفسر أوامر البايثون بإستخدام أمر import numpy. يجب علينا أن نتبع أفضل الممارسات هنا، حيث إنه من المتعارف عليه في مجتمع البايثونيين أثناء العمل على مكتبة Numpy استيراد المكتبة واعادة تسميتها باسم مختصر هو np، والهدف من ذلك هو كتابة الشيفرة بطريقة أسهل وأسرع.

نستخدم دالة np.array لإنشاء المصفوفة كالتالي:

import numpy as np
arr = np.array([1,2,3,4,5,6])
print(arr)
create_array.py

طُرق مختلفة لانشاء المصفوفات

لإنشاء مصفوفة ذات أبعاد 3X4  تتكون جميع عناصرها من الرقم 1 نستخدم الدالة np.ones:

np.ones((3,4))

لإنشاء مصفوفة بنفس الأبعاد وتكون جميع عناصرها من الرقم 0 نستخدم دالة np.zeros :

np.zeros((3,4))

لإنشاء مصفوفة من صفين و 3 أعمدة تكون جميع عناصرها من رقم نقوم بتحديده نستخدم دالة np.full :

np.full((2,2), 10)

للحصول على مصفوفة تبدأ من رقم معين وتنتهي بقيمة قبل رقم اخر مع تحديد step نستخدم دالة np.arange :

np.arange(5,30,5)

للحصول على مصفوفة تبدأ برقم معين وتنتهي برقم اخر مع تحديد عدد عناصر المصفوفة بحيث يكون مدى قيمة عناصرها بين الرقمين نستخدم الدالة np.linespace :

np.linspace(1,5,5)

بإستخدام مكتبة Numpy يُمكننا إنشاء مصفوفة الوحدة أو المصفوفة المحايدة والتي تسمى باللغة الإنجليزية ب Identity Matrix، وذلك بإستخدام أحد الدوال np.eye او np.identity.

إستيراد البيانات من ملفات خارجية

إستيراد وتصدير البيانات بالبايثون Numpy

استيراد البيانات من مصادر خارجية كملفات البيانات هو أحد الخصائص المهمة التي يحتاجها كل شخص يعمل في مجال تحليل البيانات او تعليم الآلة. يُمكننا استيراد البيناات من ملف نصي بإستخدام أحد الدالتين np.loadtxt او np.genfromtxt. لنفترض أنه لدينا ملف باسم data.txt يحتوي على نص بالشكل التالي:

my data is in text file like this
id       mobile                 com
1       0555                    0.2
2       9999                    0.1
3       6565                    0.2
4       888                       0.2
5       74744                  0.3

الأمر التالي يُمكننا من إستيراد هذه البيانات من الملف إلى بيئة العمل:

id, mobile, com = np.loadtxt('data.txt',skiprows=2,unpack=True)

في الشيفرة السابقة، قمنا أولًا بتمرير إسم الملف (الموجود في نفس مسار جلسة العمل او ملف البايثون)، ثم مررنا قيمة 2 للخاصية skiprows والتي تعني تجاهل اول سطرين من الملف (لانهم نصوص وليس أرقام)، ثم حددنا خاصية unpack حيث تكون نتيجة الدالة عبارة عن مصفوفات بعدد الأعمدة.

اذا كانت الأعمدة في الملف النصي مفصولة بفاصلة او أي رمز نصي أخر، يُمكن تحديد هذه المعلومة للدالة باستخدام الخاصية delimiter، كما يُمكننا تحديد نوع البيانات باستخدام الخاصية dtype.

تصدير المصفوفات  لملفات خارجية

قد نحتاج إلى تصدير البيانات الموجودة في المصفوفة إلى ملفات خارجية ويتم ذلك من خلال إستخدام دالة np.savetxt.

x = np.arange(0,5,0.5)
np.savetxt('test.txt',x,delimiter = ',')

وهذه ليست الطريقة الوحيدة لتصدير المصفوفات الى ملف نصي, يوجد دوال مثل save, savez, savez_compressed والتي لها أغراض مختلفة لنفس الهدف.

لمزيد من المعلومات والأمثلة حول الدوال والطرق المستخدمة لحفظ وتصدير المصفوفات في مكتبة Numpy تستطيع الذهاب هنا للقراءة أكثر والإستزادة.

خصائص المصفوفات في مكتبة Numpy

الجدول التالي يوضح الخصائص التي يُمكن الحصول عليها لمصفوفة باسم arr.

الخاصيةالمعنى
arr.shapeشكل المصفوفة
arr.ndimأبعاد المصفوفة
arr.sizeعدد عناصر المصفوفة
arr.dtypeنوع البيانات
arr.nbytesحجم عناصر المصفوفة المستخدم ب bytes
arr.itemsizeحجم العنصر الواحد في المصفوفةب bytes
arr.flagsمعلومات المصفوفة الخاصة بالذاكرة

الأن وبعد أن تعرفنا على طريقة إنشاء مصفوفة Numpy وذلك إما بإستخدام دالة np.array او عن طريق np.loadtxt و np.genfromtxt، فإنه حان الوقت للتعرف أكثر على مصفوفات Numpy وإجراء العمليات الرياضية عليها. من المهم أن نُذكر بوجود قيود على العديد من العمليات الرياضية التي يتم إجراءها على المصفوفات، من هذه القيود أنه إذا اردنا تنفيذ عملية رياضية مثل الجمع او الطرح بين مصفوفتين، فلابد أن يكون شكل المصفوفتين متوافقًا او أن يكون أحدهما من عنصر واحد، وكذلك لعملية ضرب المصفوفات والقسمة قيود اخرى. لن نتطرق في هذا المقال إلى هذه القيود والشروط بقدر ما سنركز على التعريف بالمكتبة من الجانب البرمجي.

العمليات الرياضية

العمليات الرياضية بالبايثون Numpy

نستطيع إجراء العمليات الرياضية (الجمع, الطرح, الضرب, القسمة, باقي القسمة) على المصفوفات بإستخدام الرموز المعروفة + , – , * , / , % على الترتيب أو من خلال الوظائف np.add، np.substract، np.multiply، np.divide، np.remainder. كذلك يُمكن إجراء العمليات الرياضية المتقدمة على المصفوفات مثل عملية الأس، والجذر التربيعي، والعمليات الجيبية (sin, cos) و log وعملية ضرب المصفوفات (dot multiply). هنا ستجد كل العمليات الرياضية التي يُمكن إجراءها على مصفوفات مكتبة Numpy.

بالإضافة إلى العمليات الرياضية،  فإنه من الجدير ذِكره أنه بإمكاننا أيضًا مقارنة عناصر المصفوفات ببعضها البعض بإستخدام عمليات المقارنة مثل ==  , < , > .

عند إستخدام عمليات المقارنة السابقة، يكون ناتج العملية هو مصفوفة منطقية بنفس الشكل تحتوي على قيم منطقية (True, False) تعبر عن نتيجة المقارنة لكل عنصر من المصفوفة الأولى مع العنصر الذي يقابله في المصفوفة الثانية.

import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[2,1],[4,3]])

a == b

a > b

 

وظيفة np.array_equal تُستخدم لمقارنة مصفوفتين ولكن النتيجة إما True  او False بحيث لو كاد أحد عناصر المصفوفة الأولى لا يساوي العنصر الذي يقابله في المصفوفة الثانية فإن النتيجة تكون False. بجانب عملية مقارنة مصفوفتين، لاحظ أننا نستطيع أن نُجري العمليات المنطقية مثل OR, AND, NOT على المصفوفات بإستخدام الدوال np.logical_or , np.logical_not, np.logical_and.

عمليات Subset, Slice, Index

JavaScript-Array-Slice-300x172

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

إذا كان لديك سابق معرفة عن Lists في البايثون، فستكون لديك المعرفة لإجراء العمليات السابقة، أما إذا كنت جديدًا على هذا الأمر فعليك أن تعرف النقطتين الأساسيتين التاليتين:

أولا: لابد عليك أن تكتب إسم المصفوفة متبوعًا بقوسين [  ] لإخبار البايثون بأنك تقوم بإجراء أحد العمليات السابقة.

ثانيا: غالبا، ستُمرر أرقام خاصة بين القوسين تُمثل فهارس الابتداء والانتهاء.

وبالمثال يتضح المقال.

import numpy as np

array1d = np.array([1,2,3,4,5,6])
array2d = np. array([[1, 2, 3, 4], [5, 6, 7, 8]])

عملية Subsetting

للحصول على العنصر الأول من المصفوفة array1d:

print( array1d[ 0 ] )

للحصول على العنصر في الصف رقم 1 والعمود رقم 2 من المصفوفة array2d:

print( array2d[ 1 , 2 ])

عملية Slicing

تعتبر هذه العملية مشابهة لعملية Subsetting ولكنها متقدمة أكثر، حيث هنا نحن لا نتعامل مع عناصر في أماكن معينة. ناتج عملية Slicing عبارة عن نطاق او Regions من المصفوفة. للحصول على أول ثلاثة عناصر من المصفوفة array1d:

print(array1d [ 0 : 3 ])

للحصول على عناصر الصف رقم 0 والصف رقم  1 من العمود رقم 1 من المصفوفة array2d:

print(array2d [ 0:2 , 1 ] )

عملية Indexing

سنتكلم هنا فقط عن Boolean Indexing وليس Fancy Indexing. للحصول على العناصر التي قيمتها أكبر من 3 في المصفوفة  array1d:

print( array1d[ array1d > 3 ] )

للحصول على العناصر الزوجية من المصفوفة array2d:

print( array2d[ array2d % 2 == 0 ] )

الحصول على مساعدة

في البايثون بشكل عام، يُمكن إستخدام دالة help للحصول على التوثيق الخاص بالدوال او المكتبات او الخصائص التي تتعامل معها. مكتبة Numpy تقدم حلولًا أخرى تساعد في الحصول على معلومات أكثر عن الشيفرة التي نكتبها بإستخدام دالتي np.lookfor و np.info.

التعامل مع المصفوفات في مكتبة Numpy

منقول المصفوفة Array Transpose

بإفتراض أن لدينا مصفوفة A ذات شكل 3 * 2 فإن ناتج منقول المصفوفة هو مصفوفة بنفس العناصر ولكن بترتيب مختلف تتحول فيه الصفوف لأعمدة والأعمدة لصفوف. يصبح شكل منقول المصفوفـة A هو 2 * 3. للحصول على منقول المصفوفة نستخدم الوظيفة np.transpose أو الخاصية T الموجودة للمصفوفة:

np.transpose( A )

A.T

ملاحظة/ المصفوفات ذات البعد الواحد لا تتأثر بدالة np.transpose ولا بالخاصية T.

تغيير شكل المصفوفة

ذكرنا سابقًا انه يوجد بعض القيود التي يجب أخذها بعين الإعتبار عند إجراء بعض العمليات على المصفوفات، ومن هذه القيود، توافق شكل مصفوفتين في عمليات ضرب المصفوفات Dot Multiplication. ولكن ماذا سنفعل لو كانت لدينا مصفوفات غير متوافقة الشكل؟ في هذه الحالة تأتي العمليات المسؤولة عن تغيير شكل المصفوفة أو تغيير حجمها مثل دالة np.resize.

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

np.resize( array2d, (4,6))

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

للتوضيح أكثر، لنفترض وجود مصفوفة بشكل 3*4 فإن عدد عناصرها هو 12. نستطيع أن نستخدم دالة reshape لتغيير شكل الدالة بحيث نحافظ على 12 عنصر الخاصة بها، وبذلك تكون أشكال مثل 4*3 و 6*2 و 2*6 أشكالا مقبولة وإلا سيظهر خطأ في حال استخدمنا شكلا اخر.

array2d.reshape((4,2))

طرق المصفوفة في مكتبة Numpy

تقوم دالة ravel بعملية “طرق” المصفوفة، بحيث تعمل على تحويل أي مصفوفة ذات بعد ثنائي أو أكثر إلى مصفوفة ذات بعد واحد.

array2d.ravel()

الإضافة على المصفوفة

عند إضافة عناصر إلى المصفوفة، فإن تلك العناصر تُضاف إلى نهاية المصفوفة، وذلك يتم بإستخدام دالة np.append والتي تجعل من الإضافة امرا سهلا في مصفوفات مكتبة Numpy.

لإضافة صف جديد

new_array = np.append( array2d, [[9,10,11,12]], axis = 0)

لإضافة عمود جديد

new_array = np.append(array2d,[[9],[10]],axis = 1)

لاحظ أننا إستخدمنا عند الإضافة الخاصية axis والتي تحدد مكان الإضافة، هل هي لصف أم عمود. (في المصفوفة ذات البعد الثنائي axis = 1 يعني العمود، axis = 0 يعني الصف).

للإضافة على المصفوفة ولكن في مكان محدد (ليس في اخرها) نستخدم الدالة np.insert بالطريقة التالية:

new_array = np.insert( array2d , (0,0) , 5, axis = 1)

في المثال السابق، قمنا بإضافة عمود بقيمة 5 في المكان (0,0) والذي يمثل بداية المصفوفة. للحذف من مكان معين في المصفوفة، نستخدم الدالة np.delete بنفس طريقة تحديد المكان في دالة insert.

روابط للتعلم:

1- هنا ستجد ملف Numpy_Python_Cheat_Sheet يلخص لك معلومات مهمة عن مكتبة Numpy.

2- https://www.datacamp.com/community/blog/python-numpy-cheat-sheet#gs.0_T9D90

3- http://cs231n.github.io/python-numpy-tutorial

4- http://www.python-course.eu/numpy.php

5- https://www.datacamp.com/community/tutorials/python-numpy-tutorial#gs.Ereixfc

2 thoughts

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *