6.12. الانتقاء وإعادة الترتيب¶
طوت عمليات الاختزال مصفوفة لتصبح قيمة عددية أو نتيجة برتبة أقل. أما الانتقاء فيغطي العمليات التي تختار أي العناصر يبقى وأين ينتهي بها المطاف: الاختيار الشرطي، والقص، والفرز، والبحث عن الفهارس، وإعادة الترتيب على طول محور.
6.12.1. الاختيار الشرطي¶
تُرجع where() مصفوفة تأخذ العناصر من x حيث يكون الشرط صحيحًا ومن y فيما عدا ذلك. وتُبثّ المعاملات الثلاثة معًا:
a = np.array([1, 2, 3, 4, 5], dtype=np.float)
np.where(a < 3, a, 0.0)
# array([1.0, 2.0, 0.0, 0.0, 0.0])
هذه هي الأداة المناسبة لتنفيذ "if/else لكل عنصر" دون كتابة حلقة Python.
إن clip() هي اختصار لـ maximum(lo, minimum(a, hi)) -- أي تشبيع القيم ضمن مدى:
np.clip(a, 2.0, 4.0)
# array([2.0, 2.0, 3.0, 4.0, 4.0])
تأخذ maximum() و minimum() معاملَين وتُرجعان القيمة الأكبر / الأصغر عنصرًا بعنصر:
np.maximum(a, 3.0)
np.minimum(a, np.array([5, 4, 3, 2, 1]))
6.12.2. إيجاد الفهارس¶
تُرجع nonzero() إحداثيات كل عنصر غير صفري، مقسّمة إلى مصفوفة فهارس واحدة لكل بُعد. فبالنسبة لمدخل ثنائي الأبعاد تكون النتيجة tuple مكونًا من مصفوفتين: الأولى تحتوي على فهارس الصفوف، والثانية تحتوي على فهارس الأعمدة. وإقرانهما عموديًا يعطي (row, col) لكل موضع غير صفري:
m = np.array([[0, 2, 0],
[3, 0, 0]], dtype=np.float)
np.nonzero(m)
# (array([0, 1], dtype=uint16), array([1, 0], dtype=uint16))
العناصر غير الصفرية في m هي m[0, 1] = 2 و m[1, 0] = 3. تعطي المصفوفة الأولى المُرجعة [0, 1] فهارس صفوفها؛ وتعطي الثانية [1, 0] فهارس أعمدتها. وقراءة المصفوفتين جنبًا إلى جنب تستعيد الموضعين (0, 1) و (1, 0).
هناك أيضًا عمليتا اختزال تنتجان فهارس:
argsort()-- مصفوفة أعداد صحيحة من شأنها فرز المدخلات على طول المحور المحدد (يكون الأخير افتراضيًا):a = np.array([40, 10, 30, 20], dtype=np.uint8) idx = np.argsort(a) # array([1, 3, 2, 0], dtype=uint16) a[idx] # array([10, 20, 30, 40])
تُرجع
argsortدائمًاuint16؛ ولذلك يجب ألا تحتوي المصفوفة الجاري فرزها على أكثر من 65,535 عنصرًا على المحور المفروز.
تَعُدّ bincount() تكرارات كل عدد صحيح غير سالب في مدخل أحادي البُعد من نوع uint8 / uint16
histogram = np.bincount(np.array([0, 1, 1, 2, 2, 2], dtype=np.uint8))
# array([1, 2, 3], dtype=uint16)
مفيدة لبناء مدرجات تكرارية لقيم بكسل صغيرة الأعداد دون كتابة حلقة Python.
6.12.3. الفرز وإعادة الترتيب¶
تُرجع sort() نسخة مفروزة من المصفوفة على طول المحور المحدد (الأخير افتراضيًا). استخدم sort() على المصفوفة مباشرة للحصول على نسخة فرز في المكان:
np.sort(np.array([3, 1, 2], dtype=np.float))
# array([1.0, 2.0, 3.0])
تعكس flip() الترتيب على طول المحور المحدد (كل محور عند عدم تمرير axis):
np.flip(np.array([1, 2, 3, 4]))
# array([4, 3, 2, 1])
تُزيح roll() العناصر دوريًا بالمقدار المحدد. وهي مفيدة لتنفيذ سجل إزاحة على نمط المخزن المؤقت الحلقي:
np.roll(np.array([1, 2, 3, 4]), 1)
# array([4, 1, 2, 3])
إن take() هي الصورة الصريحة للفهرسة المتطورة -- اختيار العناصر عند فهارس عشوائية:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.take(a, [0, 2, 4])
# array([10, 30, 50], dtype=uint8)
6.12.4. التصفية والتعديلات البنيوية¶
إن compress() هي الصورة الصريحة للفهرسة البوليانية -- تُرجع شرائح a المختارة بالشرط البولياني:
a = np.array([10, 20, 30, 40], dtype=np.uint8)
np.compress(a > 15, a)
# array([20, 30, 40], dtype=uint8)
تُرجع delete() نسخة بعد إزالة العناصر عند الفهارس المحددة:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.delete(a, [1, 3])
# array([10, 30, 50], dtype=uint8)
تُرجع diff() الفرق الأمامي المنفصل من الرتبة n للمصفوفة على طول محور. تُستخدم لحساب التغيرات من الدرجة الأولى بين العينات المتجاورة:
samples = np.array([1, 3, 6, 10, 15], dtype=np.float)
np.diff(samples)
# array([2.0, 3.0, 4.0, 5.0])
6.12.5. تكلفة كل عملية¶
تُرجع كل دالة تقريبًا في هذه الصفحة مصفوفة مخصصة حديثًا. مع استثناءين:
تفرز
sort()في المكان؛ بينما تُرجع الدالة الحرةsort()نسخة مفروزة.تقبل
take()الكلمة المفتاحيةout=للكتابة في مخزن مؤقت موجود مسبقًا.
في حلقة تعمل عدة مرات في الثانية، فضّل sort() التي تعمل في المكان وأعد استخدام المخازن المؤقتة المخصّصة مسبقًا في كل مكان آخر. أما الأقنعة البوليانية نفسها فيُخصَّص لها مساحة في كل مرة تُنفَّذ فيها المقارنة -- لذا ابنِ القناع مرة واحدة وأعد استخدامه عبر العمليات بدلًا من إعادة بنائه داخل كل تكرار.