نمایه سازی با آرایه‌های بولی

در بخش قبل با استفاده از عملگر‌های مقایسه‌ای روی آرایه‌ها، با آرایه‌های بولی آشنا شدیم و سپس روی آرایه‌های بولی توابعی اعمال کردیم مثل sum و count_nonzero. در این جلسه می‌خواهیم با کاربرد‌های دیگر آرایه‌های بولی آشنا شویم. در واقع به کمک آرایه‌های بولی می‌توانیم به عناصری از آرایه اصلی که ویژگی‌های خاصی دارند دسترسی پیدا کنیم.

بار دیگر نگاهی به آرایه‌ای که شامل نمرات 4 درس 4 دانش‌آموز بود نگاه کنیم.

nomarat = np.array([[20, 15, 16, 10],
                    [13, 17, 18, 11],
                    [10, 12, 14, 18],
                    [19, 15, 17, 19]])
print(nomarat)

خروجی کد:

[[20 15 16 10]
 [13 17 18 11]
 [10 12 14 18]
 [19 15 17 19]]

حال بیایید با استفاده از عملگر‌های مقایسه‌ای و منطقی جاهایی که نمره بالا مساوی 15 و کمتر مساوی 18 است را پیدا کنیم. برای این منظور داریم:

print((nomarat >= 15) & (nomarat <= 18))

خروجی کد:

[[False  True  True False]
 [False  True  True False]
 [False False False  True]
 [False  True  True False]]

نتیجه طبق انتظار ما یک آرایه بولی (True و False) است. هر جا که مقدار True وجود دارد به معنای این است که آن خانه شرایط نوشته شده را دارد و هر جا که False است به این معناست که آن خانه شرایط نوشته شده را ندارد. اما خواسته ما خود خانه‌هایی بود که شرایط ما را داشتند. به عبارت دیگر ما به دنبال مقدار نمراتی هستیم که در شرایط نوشته شده صدق می‌کند برای این منظور باید شرط نوشته شده را درون [ ] همراه نام آرایه قبل آن قرار دهیم. پس داریم:

print(nomarat[(nomarat >= 15) & (nomarat <= 18)])

خروجی کد:

[15 16 17 18 18 15 17]

پس به طور کلی می‌توانیم درون [ ] جلوی نام آرایه، یک آرایه بولی هم شکل آرایه اصلی قرار دهیم. نتیجه این کار، یک آرایه یک بُعدی شامل عناصری از آرایه اصلی است که خانه متناظرشان در آرایه بولی مقدار True داشته باشد. به این کار اصطلاحاً ماسک کردن (Masking) هم می‌گویند. بدین ترتیب، به کمک این نوع از نمایه سازی به سادگی زیر مجموعه مورد نظرمان را از آرایه اصلی استخراج می‌کنیم. چند مثال دیگر ببینیم.

در زیر می‌خواهیم میانگین نمراتی که بالا مساوی 17 هستند و همچنین میانه نمرات بین 10 تا 15 را محاسبه کنیم داریم.

nomarat = np.array([[20, 15, 16, 10],
                    [13, 17, 18, 11],
                    [10, 12, 14, 18],
                    [19, 15, 17, 19]])
print('nomarat:')
print(nomarat)
print('nomarat >= 17:')
print(nomarat[nomarat >= 17])
print('mean:')
print(np.mean(nomarat[nomarat >= 17]))
print('nomarat > 10 & nomarat < 15:')
print(nomarat[(nomarat > 10) & (nomarat < 15)])
print('median:')
print(np.median(nomarat[(nomarat > 10) & (nomarat < 15)]))

خروجی کد:

nomarat:
[[20 15 16 10]
 [13 17 18 11]
 [10 12 14 18]
 [19 15 17 19]]
nomarat >= 17:
[20 17 18 18 19 17 19]
mean:
18.285714285714285
nomarat > 10 & nomarat < 15:
[13 11 12 14]
median:
12.5

در کد بالا ابتدا خود آرایه را چاپ کردیم. سپس زیر بخشی که نمرات بزرگتر مساوی 17 دارد را چاپ کردیم و در نهایت میانگین این زیر بخش را حساب کردیم. در ادامه زیر بخشی که نمرات بین 10 تا 15 دارد را چاپ کردیم و در ادامه میانه این بخش را چاپ کردیم.

نمایه سازی با آرایه‌های عددی

نمایه سازی با آرایه‌های بولی برای انتخاب خانه‌هایی از آرایه اصلی که شرایط خاصی را داشتند استفاده می‌شد (در بخش بالا مثال‌هایی را دیدیم). اما گاهی مواردی پیش می‌‎آید که ما به دنبال خانه‌هایی از آرایه اصلی بر حسب جایگاهشان هستیم. برای این منظور از آرایه‌های عددی برای نمایه سازی استفاده می‌کنیم. ( در عنوان قبل نمایه سازی بر اساس آرایه‌های بولی بود، اما در این عنوان می‌خواهیم نمایه سازی بر اساس آرایه‌های عددی را معرفی کنیم که این اعداد جایگاه‌های مورد نظر ما در آرایه اصلی هستند).حال به بررسی یک مثال می‌پردازیم.

در مثال زیر یک آرایه با 5 عدد نوشته‌ایم و می‌خواهیم خانه‌های شماره 1 و 6 و 3 (با شروع از صفر) از آن را جدا کنیم. داریم:

a = np.array([2, 4, 10, 7, 8, 12, 17])
myIndex = [1, 6, 3]
print(a[myIndex])

خروجی کد:

[ 4 17  7]

توجه کنیم که آرایه برگردانده شده هم شکل با آرایه نمایه سازی (همان آرایه‌ای که در آن شماره خانه‌ها یا جایگاه‌های مورد نظر را ذخیره کرده‌ایم) است. مثلاٌ در مثال بالا آرایه نمایه سازی شده یک بُعدی بود بنابراین خروجی نیز یک بُعدی شد.

حال یک آرایه نمایه سازی دو بُعدی را در نظر می‌گیریم (آرایه اصلی همان آرایه a در بالا است).

myNewIndex = np.array([[1, 6],
                       [2, 0]])
print(a[myNewIndex])

خروجی کد:

[[ 4 17]
 [10  2]]

در مثال بالا شماره خونه‌های 1 و 6 و 2 و 0 را از آرایه اصلی به صورت دو بُعدی استخراج کرده‌ایم.

نمایه سازی عددی برای آرایه‌های چند بُعدی

نمایه ‌سازی عددی را می‌توان برای آرایه‌های چند بُعدی نیز انجام داد. برای این منظور، باید مختصات خانه‌هایی که می‌خواهیم برای هر بُعد به صورت جدا در یک آرایه نگه داریم. سپس از این آرایه‌ها برای نمایه سازی استفاده می‌کنیم. برای مثال اگر آرایه ما دو بُعدی باشد باید یک آرایه شامل سطر‌ها و یک آرایه شامل ستون‌های خانه‌های مورد نظر خود بسازیم و سپس آن‌ها را درون [ ] همراه نام آرایه بیاوریم. مثال زیر را ببینیم.

a = np.array([[3, 4, 12, 8],
              [10, 9, 20, 2],
              [8, 7, 2, 19]])
print("a:")
print(a)
rows = np.array([0, 0, 1, 2])
columns = np.array([1, 3, 2, 1])
print("a[rows, columns]:")
print(a[rows, columns])

خروجی کد:

a:
[[ 3  4 12  8]
 [10  9 20  2]
 [ 8  7  2 19]]
a[rows, columns]:
[ 4  8 20  7]

 در مثال بالا آرایه a یک آرایه دو بُعدی 3 در 4 است که ما می‌خواهیم خانه‌های (0,1) که عدد 4 در آن است. و خانه (0,3) که عدد 8 در آن است. و خانه (1,2) که عدد 20 در آن است. و خانه (2,1) که عدد 7 در آن است را استخراج کنیم. برای این منظور شماره ردیف‌های مورد نظر را درون آرایه rows و شماره ستون‌های مورد نظر را درون آرایه column ذخیره کردیم و سپس درون [ ] به همراه نام آرایه اصلی (یعنی a) نوشتیم. مشاده می‌کنیم که خانه‌های گفته شده درون آرایه خروجی قرار دارد.

توسعه دهندگان
احمدرضا آهنگریان