Path: blob/master/deprecated/introduction-to-numpy.ipynb
675 views
Kernel: Python 3 (ipykernel)
In [1]:
Out[1]:
تعتبر مكتبة numpy واحدة من اشهر المكتبات العلمية الخاصة بالتعامل مع المتجهات والمصفوفات في بايثون. كما انها تعتبر البنية الرئيسية لبقية المكتبات العلمية الاخرى مثل مكتبة scipy ومكتبة matplotlib ومكتبة pandas الخ ... وتم اشتقاق اسم هذه المكتبة من الكلمتين الانجليزيتين numerical python. وهي مكتبة مفتوحة المصدر تم انشاؤها بوسطة ترفس اوليفنت Travis Oliphant في عام 2005 عندما قام بدمج مكتبتين مشهورتين في ذلك الوقت احدهما تسمى Numerics والاخرى تدعى Numarray. وتعتبر هذه المكتبة اذا ما اضيفت لها مكتبة matplotlib و scipy بديلا مناسبا للبرنامج الشهير matlab. وسوف نتعرف في هذا الفصل على اساسيات التعامل مع هذه المكتبة وكيفية اجراء العمليات الحسابية من خلالها.
أهداف الفصل
عند اتمام هذا الفصل يجب ان يكون لديك المام بالآتي:- التعرف على نوع البيانات التجميعية التي تتعامل معها مكتبة numpy.
- التعرف على كيفية انشاء مصفوفة في مكتبة numpy.
- التمييز بين الانواع الأساسية للبيانات التجميعية من خلال معرفة خصائص كل نوع.
تنصيب مكتبة numpy
لا تأتي مكتبة numpy مدمجمة مع الاصدارة الاصلية لبايثون وتحتاج منا ان نقوم بتنصيبها قبل استخدامها. ويمكن القيام بتنصيب مكتبة numpy بكل يسر وسهولة باستخدام الاداة pip التي تأتي مدمجة مع اصدارة بايثون بكتابة الامر التالي في محرر الاوامر لنظام التشغيل الذي نستخدمه كما يلي:
In [2]:
Out[2]:
Requirement already satisfied: numpy in c:\users\al7ak\anaconda3\lib\site-packages (1.19.3)
Note: you may need to restart the kernel to use updated packages.
اما اذا قمت بتنصيب توزيعة Anaconda فان مكتبة numpy تأتي مدمجة مع هذه التوزيعة ولا تحتاج الى تنصيب. بل يكفي ان نستدعيها في الملف الذي نريد ان نستخدمها فيه.
استدعاء مكتبة numpy
كل ما تعلمته سابقاً من طرق استدعاء المكتبات ينطبق تماما على مكتبة numpy. ولكن تم التعارف من قبل مجتمتع بايثون على استدعاء مكتبة بايثون بالطريقة التالية:
In [3]:
كيفية انشاء مصفوفة numpy
ترتكز حسابات مكتبة numpy على بيان تجميعي يدعى ndarray وهو عبارة عن مصفوفة متعددة الابعاد تحتوي على بيانات من نوع واحد من البيانات الاساسية. وهذه الخاصية تجعلها مختلفة عن القوائم في بايثون. فالقوائم في بايثون تسمح لنا بالتعامل مع بيانات مختلطة بحيث يمكن ان تحتوي القائمة في بايثون على قيم عددية وقيم نصية وقيم منطقية في نفس الوقت بينما مصفوفة ndarray لا تسمح بتكوينها الا ببيانات من نفس النوع. حتى البيانات العددية لا بد ان تكون من نفس النوع ايضا فهي اما ان تكون جمعيها اعداد صحيحة او اعداد عشرية او اعداد مركبة. وسوف نتكلم عن هذا الموضوع بشيئ من التفصيل ولكن بعد ان نتعرف على الطريقة التي يمكن لنا ان ننشئ بها مصفوفة numpy.
ويمكن تكوين مصفوفة numpy باستخدام الدالة ()array مع قائمة من قوائم بايثون كما في المثال التالي:
In [175]:
Out[175]:
array([5, 6, 7])
او باستخدام الدالة نفسها مع صف من صفوف بايثون كما في ا لمثال التالي:
In [176]:
Out[176]:
array([5, 6, 7])
فالمصفوفتان السابقتان تعتبران احادية البعد لانهما تحتويان على قائمة واحدة او صف واحد فقط. ويمكن التعرف على بعدها باستخدام الخاصية ndim كما في المثال التالي:
In [25]:
Out[25]:
1
ويمكن انشاء مصفوفة ذات بعدين من خلال اضافة قائمة داخل قائمة او صف داخل قائمة عند استخدام الدالة ()array كما في المثالين التاليين:
In [17]:
Out[17]:
2
In [181]:
Out[181]:
2
ويمكن زيادة بعد المصفوفة بزيادة عدد القوائم الداخلية كما في المثال التالي:
In [18]:
Out[18]:
4
ويمكن التحكم ببعد المصفوفات من خلال استخدام المدخل الاختياري ndmin عند انشاء المصفوفة كما في المثال التالي:
In [184]:
Out[184]:
3
لاحظ ان التحكم ببعد المصفوفة بهذه الطريقة يتطلب فقط ادخال قائمة او صف وليس قائمة داخل قائمة او صف داخل قائمة كما فعلنا في الطريقة الاعتيادية سابقا
وللتعرف على عدد صفوف واعمدة المصفوفات السابقة نستخدم الخاصية shape كما في المثال التالي:
In [28]:
Out[28]:
(3,)
وتعنى النتيجة السابقة ان المصفوفة احادية البعد ويمكن الاشارة الى عناصرها برقم واحد يسمى المؤشر يوضع بين قوسين مربعين بعد اسم المصفوفة ليشير الى القيمة داخل المصفوفة التي يشير اليها المؤشر كما في المثال التالي:
In [10]:
Out[10]:
6
اما المصفوفة ثنائية البعد فان استخدام خاصية shape سوف تعطي رقمين الاول يشير الى عدد الصفوف والاخر يشير الى عدد الاعمدة كما في المثال التالي:
In [29]:
Out[29]:
(1, 3)
وتحتاج المصفوفة ثنائية البعد الى مؤشرين لمعرفة القيم داخل المصفوفة كما في المثال التالي:
In [30]:
Out[30]:
7
فالرقم الاول من اليسار يدل على رقم الصف والقيمة الثانية تدل على رقم العمود. فلو كان لدينا مصفوفة ثنائية مكونة من ثلاث صفوف وثلاثة اعمده كما في المثال التالي:
In [31]:
Out[31]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
ولو اردنا الاشارة الى القيمة 8 في المصفوفة لكتبنا الكود على النحو التالي:
In [33]:
Out[33]:
8
كما يمكن تكوين مصفوفة صفرية باستخدام الدالة ()zeros كما في المثال التالي
In [34]:
Out[34]:
array([0., 0., 0.])
فادالة الصفرية السابقة تقوم بتكوين مصفوفة احادية البعد جميع بياناتها اصفار ويتم تحديد عدد هذه الاصفار من خلال رقم يكتب داخل قوسي هذه الدالة.
اما اذا اردنا تكوين مصفوفة ذات بعدين فاكثر فاننا نحتاج الى قوسين مربعين نضع داخلها قيما تمثل عدد الاصفار في كل بعد كما في المثال التالي:
In [39]:
Out[39]:
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
In [40]:
Out[40]:
array([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
لانشاء مصفوفة جميع قيمها العدد واحد نستخدم الدالة ()ones كما في المثال التالي:
In [41]:
Out[41]:
array([1., 1., 1., 1.])
In [43]:
Out[43]:
array([[1., 1.],
[1., 1.]])
لاحظ التشابه الكبير بين الدالة الصفرية والدالة الاحادية من ناحية شكل الكود البرمجي
كما يمكن ايضا تكوين دالة بقيم عشوائية تتناسب قيمها مع حالة الذاكرة من خلال استخدام الدالة ()empty كما في المثال التالي:
In [170]:
Out[170]:
array([[ 0., 20000., 40000.],
[ 60000., 80000., 100000.]])
كما يجب الاشارة الى ان القيم الافتراضيية للدوال الثلاث السابقة هي من النوع العشري float
ولانشاء مصفوفة ذات بعد احادي بحيث تكون قيم هذه المصفوفة متباعده عن بعضها البعض بقيمة معينة نستخدم الدالة ()arange بنفس الطريقة التي تعلمنا استخدامها مع الدالة ()range عند انشاء القوائم في بايثون. شاهد المثال التالي:
In [44]:
Out[44]:
array([4. , 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5. , 5.1, 5.2,
5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9])
لاحظ ان هناك اختلاف جوهري بين دالة ()arange في مكتبة numpy ودالة ()range في مكتبة بايثون القياسية وهو ان الدالة ()arange في numpy تمكننا من استخدام الاعداد الصحيحية والعشرية على حد سواء. بينما الدالة ()range فانها تستوجب استخدام اعداد صحيحة فقط كما في المثال التالي:
In [46]:
Out[46]:
array([3. , 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4. , 4.1, 4.2,
4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9])
In [45]:
Out[45]:
array([3, 4])
In [47]:
Out[47]:
range(3, 5)
In [48]:
Out[48]:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_1526/2339599927.py in <module>
----> 1 range(3.0,5.0)
TypeError: 'float' object cannot be interpreted as an integer
فرسالة الخطأ السابقة تبين لنا ان الدالة ()range لايمكنها التعامل مع الاعداد العشرية.
كما يمكن انجاز المهمة السابقة باستخدام الدالة ()linspace ايضا من مكتبة numpy كما في المثال التالي:
In [49]:
Out[49]:
array([3. , 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4. , 4.1, 4.2,
4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5. ])
لاحظ ان الفرق بين الدالتين ()arange والدالة ()linspace هو ان الدالة ()arange تتطلب مقدار التباعد في المجال المعطى. واذا لم يكن مقدار التباعد معطى فان القيمة الافتراضية تكون 1. اما الدالة ()linspace فهي تتطلب المجال وعدد القيم التي يجب انشاؤها بحيث تقوم بتحديد مقدار التباعد تلقائيا من ذاتها. في حال عدم تزويد الدالة ()linspace بعدد القيم المطلوبة فان القيمة الافتراضية لعدد القيم التي سوف تنتجها الدالة سوف يكون 50 كما في المثال التالي:
In [50]:
Out[50]:
50
لاحظ ايضا ان الدالة ()linspace تتطلب ان يكون مجال المصفوفة يتكون من قيمتين قيمة للبداية وقيمة للنهاية اما الدالة arange() فعند تزويدها بقيمة واحدة في المجال فانها سوف تفترض ان هذه القيمة هي قيمة النهاية وقيمة البداية للمجال سوف تفترض انها مساوية للعدد 0. كما في المثال التالي:
In [5]:
Out[5]:
array([0, 1, 2, 3])
In [6]:
Out[6]:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_948/2128360098.py in <module>
----> 1 np.linspace(4)
<__array_function__ internals> in linspace(*args, **kwargs)
TypeError: _linspace_dispatcher() missing 1 required positional argument: 'stop'
وتستخدم الدالة ()logspace لتكوين مصفوفة احادية البعد وبقيم تباعد لغورتمية بين عناصرها كما في المثال التالي:
In [168]:
Out[168]:
array([1.e+01, 1.e+02, 1.e+03, 1.e+04, 1.e+05, 1.e+06, 1.e+07, 1.e+08,
1.e+09, 1.e+10])
لاحظ ان قيم البداية والنهاية للدالة ()logspace تمثل اس العدد 10
تمارين استكشافية
١- استكشف الفرق بين استخدام قيمة واحدة مع الدالة ()range من مكتبة بايثون القياسية والدالة ()arange من مكتبة numpy ؟
In [ ]:
٢- استكشف الفرق في اخر قيمة تنتج من انشاء مصفوفتين احاديتن احدهما تم انشاؤه باستخدام الدالة ()arange والاخرى باستخدام الدالة ()linspace من مكتبة numpy للمجال من 2 الى 3 متباعدة عن بعضها البعض بمقدار 0.5 ؟
In [ ]:
3 هل يوجد هناك ما يسمى بالمصفوفة ذات البعد صفر؟ واذا كانت الاجابة بنعم فكيف يمكن تكوينها؟ وماذا يمكن ان نعبر عنها رياضيا؟
In [ ]:
خصائص numpy
هناك عدة خصائص للمصفوفات في numpy تعلمنا منها الى حد الان على خاصيتين الا وهما خاصية عدد الابعاد ndim وخاصية شكل المصفوفة shape وسوف نكمل هنا بعضا من هذه المخصائص التي نعتقد ان من الاهمية بمكان ان يتعرف عليها الدارس وهي على النحو التالي:
اولا: خاصية عدد الابعاد
ثانيا: خاصية شكل المصفوفة
ثالثاً: خصاصية الحجم size
ويمكن التعرف على عدد البيانات داخل مصفوفة باستخدام خاصية الحجم size كما في الامثلة التالية:
In [52]:
Out[52]:
1
In [53]:
Out[53]:
3
In [54]:
Out[54]:
6
In [55]:
Out[55]:
2
رابعاً: خاصية نوع البيان dtype
انواع البيانات الاساسية في بايثون كما تعلمنا سابقاً هي خمسة انواع رئيسية:
- الاعداد الصحيحة integers وتكتب اختصارا int
- الاعداد العشرية float
- الاعداد المنطقية boolean وتكتب اختصاراً bool
- الاعداد المركبة complex
- النصوص string وتكتب اختصاراً str
اما في مكتبة numpy فان انواع البيانات الاساسية هي احدى عشر نوعا رئيسياً:
- الاعداد الصحيحة integers وتشمل السالبة والموجبة ويرمز لها بالحرف i
- الاعداد الصحيحة بدون اشارة اي الموجبة فقط unsigned integers ويرمز لها بالحرف u
- الاعداد المنطقية boolean ويرمز لها بالحرف b
- الاعداد العشرية float ويرمز لها بالحرف f
- الاعداد المركبة العشرية compex float ويرمز لها بالحرف c
- بيانات فارق الوقت timedelta ويرمز لها بالحرف m
- بيانات التاريخ والوقت datetime ويرمز لها بالحرف M
- الكائنات البرمجية object ويرمز لها بالرمز O
- البيانات النصية string ويرمز لها بالحرف S
- البيانات النصية ذات الترميز العالمي unicode ويرمز لها بالحرف U
- الانواع الاخرى من البيانات void ويرمز لها بالحرف V
ولتعرف على نوع البيانات التي بداخل المصفوفة نستخدم الخاصية dtype كما في المثال التالي:
In [6]:
Out[6]:
dtype('int32')
In [56]:
Out[56]:
dtype('int64')
In [57]:
Out[57]:
dtype('float64')
In [58]:
Out[58]:
dtype('bool')
In [59]:
Out[59]:
dtype('<U6')
تعرفت من قبل على ان int تعنى اعداد صحيحة ولكن ما يمكن ان يستثير تساؤلاتك هو الرقم الذي يتلو int. ماذا يمكن ان يعني هذا الرقم. للاجابة على هذا التساؤل والذي يمكن ان يكون تخمينك قد هداك الى االاجابة الصحيحة هو ان الرقم الذي يتلو int يمثل عدد البتات bits التي يتم حجزها في الذاكرة لكل بيان في المصفوفة. وهذه خاصية اخرى تتميز بها مصفوفة numpy عن قوائم بايثون فهي تسمح للمستخدم التحكم الكامل بالمساحة التي يمكن ان تشغلها البيانات في ذاكرة الكمبيوتر. لكن هذا التحكم ليس مطلقا وانما محدود بقيم ثابته لايمكن للمستخدم ان يستخدم قيما سواها كما هو موضح في الجدول التالي:
نوع البيان | الوصف |
---|---|
int64 | عدد صحيح يمثل بـ 64 بت او 8 bytes |
int32 | عدد صحيح يمثل بـ 32 بت او 4 bytes |
int16 | عدد صحيح يمثل بـ 16 بت او 2 bytes |
int8 | عدد صحيح يمثل بـ 8 بت او 1 bytes |
float64 | عدد عشري يمثل بـ 64 بت او 8 bytes |
float32 | عدد عشري يمثل بـ 32 بت او 4 bytes |
float16 | عدد عشري يمثل بـ 16 بت او 2 bytes |
complex64 | عدد مركب يمثل بـ 64 بت او 8 bytes |
complex128 | عدد مركب يمثل بـ 128 بت او 16 bytes |
bool | عدد منطقي يمثل بـ 8 بت او 1 bytes |
لاحظ ايضا ان البيانات النصية تمثل باستخدام علامة المقارنة اصغر من > والحرف U للتدل على ان البيانات هي بيانات نصية يتم ترميزها بالترميز unicode متبوعاً بعدد الحروف لاكبر بيان نصي موجود
ويمكن ايضا تحديد نوع بيانات المصفوفة عند بداية تكوينها من خلال استخدام المدخل الاختياري dtype داخل قوسي الدالة ()array كما في المثال التالي:
In [169]:
Out[169]:
array([[1.+0.j, 2.+0.j],
[3.+0.j, 4.+0.j]])
خامساً: خاصية مقاس البيان itemsize
كما تعلمنا سابقاً مصفوفة numpy تحجز عدد مساويا من المساحة في الذاكرة لكل بيان موجود فيها ولتعرف على مقدار البايتات التي يشغلها كل بيان من ذاكرة الكمبيوتر يمكننا الاستعانة بالخاصية itemsize كما في الامثلة التالية:
In [8]:
Out[8]:
8
In [9]:
Out[9]:
8
In [10]:
Out[10]:
1
In [11]:
Out[11]:
24
In [ ]: