مرتب سازی آرایه
یکی از کارهای بسیار پرکاربرد در کار با دادهها مرتب سازی یک آرایه است. برای این منظور الگوریتمها (روشهای) متفاوتی وجود دارد. برای نمونه میتوان به الگوریتم مرتب سازی حبابی، الگوریتم مرتب سازی درجی و ... نام برد. تفاوت این الگوریتمها در سرعت و روند مرتب سازی آن آرایه است. در بین الگوریتمها، الگوریتم مرتب سازی سریع (Quick Sort) سرعت بالایی دارد که پیش فرض دستور مرتب سازی در پایتون و نامپای است.
برای مرتب سازی یک آرایه در نامپای از دستور ()np.sort استفاده میشود. به مثال زیر توجه کنید:
a = np.array([12, 9, 2, 3, 5, 8])
print(np.sort(a))
خروجی کد:
[ 2, 3, 5, 8, 9, 12]
نکته: دستور ()np.sort آرایه را از کم به زیاد مرتب میکند و نکته دیگر این که دستور ()np.sort آرایه را تغییر نمیدهد بلکه یک آرایه جدید که مرتب شده آرایه اصلی است، تولید میکند.
حتی میتوانیم عمل مرتب سازی را در راستای محور خاصی انجام دهیم. به مثال زیر توجه کنید:
a = np.array([[4, 12, 7],
[2, 1, 9],
[5, 3, 10],
[11, 8, 17]])
print(np.sort(a, axis=0))
در کد بالا یک آرایه دو بُعدی 4 در 3 (4 سطر و 3 ستون) داریم که آن را در راستای محور 0 (جهت بالا به پایین) مرتب کردهایم. حال به خروجی نگاه کنیم:
[[ 2, 1, 7],
[ 4, 3, 9],
[ 5, 8, 10],
[11, 12, 17]]
حال بیایید تا در راستای محور 1 (جهت چپ به راست) مرتب کنیم. به کد زیر توجه کنید:
a = np.array([[4, 12, 7],
[2, 1, 9],
[5, 3, 10],
[11, 8, 17]])
print(np.sort(a, axis=1))
خروجی کد بالا:
[[ 4 7 12]
[ 1 2 9]
[ 3 5 10]
[ 8 11 17]]
تابع ()np.argsort:
اگر بخواهیم برای این تابع توضیحی آوریم کمی کار را سخت میکند پس با مثال توضیح میدهیم. به مثال زیر توجه کنید:
a = np.array([3, 10, 6, 7, 4, 2])
b = np.argsort(a)
print(b)
حال خروجی را نگاه کنیم:
[5 0 4 2 3 1]
در خروجی بالا در خانه صفراُم، شماره خانه 5 قرار دارد. به این معنی که 5 اُمین خانه از آریه a کوچکترین است. (یعنی عدد 2)
در خانه یک اُم، شماره خانه 0 قرار دارد. به این معنی که 0 اٌمین خانه از آرایه a دومین عدد کوچک است. (یعنی عدد 3)
جبر خطی
در جبر خطی ماتریسها و بردارها به وفور دیده میشوند و بسیار پرکاربرد و مهم هستند. از ماتریسها و بردارها برای نمایش دادهها در کنار هم نیز استفاده میشود که شما تا اینجا مثالهای بسیاری را دیدید. مثلا یک آرایه تک بُعدی 5 عضوی، یا یک آرایه دو بُعدی 3 در 4(که همان ماتریس است).
عملیات جبر خطی بسیاری داریم که روی ماتریسها (آرایههای دو بُعدی) و بردارها (آرایههای تک بُعدی) انجام میشود. یکسری از این عملیات و توابع را دیدیم مثل جمع نظیر به نظیر (توسط دستور ()np.add)، تفریق نظیر به نظیر (توسط دستور ()np.subtract) و ... . اما یکسری از توابع و عملیاتها هستند که هنوز با آنها آشنا نشدیم مثل ضرب ماتریسی.
نکته: ضرب ماتریسی با ضرب نظیر به نظیر دو ماتریس فرق میکند. ضرب نظیر به نظیر توسط دستور ()np.multiply انجام میشود.
برای ضرب ماتریسی از دستور ()np.matmul و یا ()np.dot استفاده میکنیم.
این دو تابع اگر دو آرایه یک بُعدی هم اندازه در ورودی بگیرند با آنها مثل بردار رفتار میکنند و نتیجه ضرب داخلی آن را (یعنی ضرب نظیر به نظیر اعضای دو بردار و سپس جمع آنها که یک عدد تنها میشود) بر میگرداند.
اگر یک بردارو یک ماتریس (یعنی یک آرایه یک بُعدی و یک آرایه دو بُعدی) در ورودی بگیرد نتیجه آن یک بردار است. که نشان دهنده ضرب بردار در ماتریس است.
اگر دو ماتریس (دو آرایه دو بُعدی) در ورودی بگیرد، خروجی آن یک آرایه دو بُعدی خواهد بود.
حال برای هر یک مثالهایی را میآوریم.
دوبردار:
v1 = np.array([3, 1, 2, 4])
v2 = np.array([1, 1, 2, 2])
print(np.matmul(v1, v2))
print(np.dot(v1, v2))
خروجی کد:
16
16
یک بردار و یک ماتریس:
v1 = np.array([3, 1, 2, 4])
m1 = np.array([[2, 8],
[5, 1],
[9, 3],
[2, 8]])
print(np.matmul(v1, m1))
print(np.dot(v1, m1))
خروجی کد:
[37 63]
[37 63]
نکته: در این حالت حتماً باید ابتدا بردار نوشته شود و سپس ماتریس. باید توجه کنیم که تعداد سطرهای ماتریس حتماً باید با تعداد اعضای بردار یکی باشد. مثلاً در مثال بالا بردار ما 4 عضو دارد و همچنین ماتریس ما 4 سطر دارد بنابراین قابل ضرب هستند.