مهدی عادلی فر
بنیانگذار توسینسو و برنامه نویس

آموزش کار با آرایه ها در کتابخانه Numpy پایتون

در این مطلب در مورد کار با آرایه ها بوسیله کتابخانه Numpy در پایتون صحبت می کنیم و با روش های مختلفی مانند ساخت زیر آرایه، ادغام آرایه ها و ... آشنا خواهیم شد.

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران

ساخت یک زیر آرایه از آرایه

همانطور که در مطالب قبلی گفته بودیم با استفاده از [] می‌توان به اعضای یک آرایه دسترسی داشت. حال با استفاده از علامت کولون (:) می‌توان یک قطعه از آرایه را به عنوان آرایه جدید در نظر گرفت. روش نوشتن این حالت به شکل زیر است:

x[start:stop:step]

در فرمول بالا start محل شروع آرایه و stop محل پایان آرایه و step گام های جدا کردن آرایه جدید است که در ادامه با مثال بیشتر توضیح می‌دهیم. در فرمول بالا اگر هر کدام از ۳ ورودی مشخص نشده باشد به طور پیش‌فرض مقادیر زیر را خواهند داشت. Start=0 و مقدار stop=سایز آرایه و مقدار step برابر ۱ خواهد بود. در نظر بگیرید که یک آرایه از ۰ تا ۹ را داریم که در آرایه x ذخیره شده است یعنی کد زیر

x = np.arange(10)

حال اگر بخواهیم 5 عنصر اول این آرایه را جدا کنیم از کد زیر استفاده می کنیم. در کد زیر stop برابر5 گذاشته شده است.

x1 = x[:5]

و اگر بخواهیم عناصر بعد از اندیس 5 را به دست آوریم کد زیر را می نویسیم. در کد زیر start برابر 5 گذاشته شده است.

x1 = x[5:]

حال اگر بخواهیم عناصر وسطی آرایه یعنی 4 تا 7 را به دست آوریم از کد زیر استفاده می کنیم.

x1 = x[4:7]

اگر بخواهیم از آرایه x فقط اعضای زوج را به دست آوریم باید step را برابر ۲ قرار دهیم مانند کد زیر

x1 = x[::2]

و اگر بخواهیم اعضای فرد را پیدا کنیم باز هم step را برابر ۲ قرار می‌دهیم ولی start  را نیز ۱ می کنیم. به شکل زیر

x1 = x[1::2]

یکی از حالت‌هایی که کمی گیج‌کننده است این است که مقدار step منفی شود. در این صورت مقادیر پیش‌فرض برای start و stop عوض می شود. برای مثال اگر بخواهیم یک آرایه را برعکس کنیم فقط باید مقدار step را -1 قرار دهیم مانند کد زیر

x1 = x[::-1]

و اگر بخواهیم که عناصر کوچکتر از ۵ از آرایه به صورت برعکس خوانده شوند به صورت زیر عمل می کنیم.

x1 = x[5::-1]

و اگر بخواهیم که در مثال قبل اعداد کوچکتر از 5 به صورت برعکس و یکی درمیان برگردانده شوند step را -2 قرار می دهیم.

ساخت زیرآرایه از آرایه چندبعدی

کار با آرایه های دوبعدی و چندبعدی نیز دقیقاً شبیه به همان فرمولی است که برای آرایه های یک بعدی گفته شد با این تفاوت که برای هر بعد جدا حساب کرده و در نهایت بعد ها را با ویرگول جدا می کنیم. برای مثال x2 را آرایه زیر در نظر بگیرید.

x2 = np.array([[12, 5, 2, 4], [7, 6, 8, 8], [1, 6, 7, 7]])

که این آرایه به شکل زیر است

[[12  5  2  4]
 [ 7  6  8  8]
 [ 1  6  7  7]]

اگر بخواهیم دو سطر و ۳ ستون اول آرایه بالا را جدا کنیم باید از کد زیر استفاده کنیم

x3=x2[:2, :3]

که خروجی آن به شکل زیر خواهد بود

[[12  5  2]
 [ 7  6  8]]

و اگر بخواهیم همه سطرها را داشته باشیم ولی ستون‌ها یکی در میان باشد:

x3=x2[::, ::2]

که خروجی به شکل زیر خواهد بود

[[12  2]
 [ 7  8]
 [ 1  7]]

همچنین برای اینکه یک آرایه دوبعدی را برعکس کنیم مانند آرایه یک بعدی فقط باید step  ها را -1 کنیم مانند مثال زیر

x3=x2[::-1, ::-1]

همچنین می‌توان به راحتی هرکدام از سطرها و ستون‌های آرایه را جدا کرد و در یک آرایه یک بعدی ذخیره کرد. برای مثال اگر من بخواهم در آرایه x2 ستون اول را به عنوان یک آرایه جدا کنم به شکل زیر عمل می کنم.

x3=x2[::, 0]

در کد بالا دقت کنید که برای سطرها از حالت جدا کردن استفاده کرده‌ایم و برای ستون‌ها شماره ستون را قرار داده‌ایم که خروجی آن به شکل زیر خواهد بود.

[12  7  1]

همچنین برای اینکه بخواهیم سطر دوم از آرایه x2 را به دست آوریم کد زیر را می نویسیم

x3=x2[1, ::]

که خروجی به شکل زیر است

[7 6 8 8]

نکته مهمی که وجود دارد این است که اگر با روش بالا یک زیر آرایه از آرایه اصلی درست کنید به این معنی نیست که یک آرایه جدید ساخته شده است بلکه  این زیر آرایه یک رفرنس به آرایه اصلی است و اگر تغییری در این آرایه داده شود آرایه اصلی هم تغییر می‌کند برای مثال اگر ما یک زیر آرایه ۲در۲ را از آرایه x2 جدا کنیم و مقدار آن را تغییر دهیم می‌بینیم که آرایه اصلی هم تغییر کرده است مانند کد زیر

x4=x2[:2,:2]
x4[0,1]=150
print(x2)

حال خروجی کد بالا به شکل زیر خواهد بود

[[ 12 150   2   4]
 [  7   6   8   8]
 [  1   6   7   7]]

همانطور که در خروجی دیده می‌شود عنصر دوم از آرایه x2 نیز مقدار 150 قرار گرفته است. حال برای اینکه یک زیر آرایه جدید ساخته شود و وابسته به آرایه اصلی نباشد باید از تابع copy استفاده کنید یعنی در مثال قبل خط اول را به شکل زیر تغییر دهیم.

x4=x2[:2,:2].copy()

تغییر شکل آرایه ها

یکی از کارهای پرکاربردی که می‌توان با numpy انجام داد این است که یک آرایه را تغییر شکل دهیم برای مثال یک آرایه یک بعدی که ۹ عنصر دارد را یه یک آرایه ۲ بعدی ۳در۳ تبدیل کنیم برای این کار از تابع reshape استفاده می کنیم. مانند کد زیر

grid = np.arange(1, 10).reshape((3, 3))

خروجی برنامه بالا به شکل زیر خواهد بود

[[1 2 3]
[4 5 6]
[7 8 9]]

دقت داشته باشید که هنگامی که از تابع reshape استفاده می‌کنید باید تعداد اعضا با حالت چندبعدی متناسب باشد یعنی نمی‌توان با ۵ تا عنصر یک آرایه دوبعدی ۳در۳ ساخت. همچنین به این نکته دقت کنید که عمل reshape کردن از آرایه اصلی کپی نمی گیرد.

چسباندن آرایه ها به همدیگر

کارهایی که تاکنون گفتیم فقط بر روی یک آرایه کار می‌کردند ولی اگر بخواهیم مثلاً دو آرایه را با هم ترکیب کنیم و یک آرایه به دست آوریم باید به شکل زیر عمل کنیم.

x = np.array([1, 2, 3])
y = np.array([3, 2, 1])
z=np.concatenate([x, y])
print(z)

که خروجی آن به شکل زیر است

[1 2 3 3 2 1]

تابع concatenate می‌تواند بیشتر از ۲ آرایه بگیرد و می‌توانید چند تا آرایه را با هم ترکیب کنید. همچنین از این تابع می‌توان برای آرایه های چند بعدی نیز استفاده کرد. برای مثال

grid = np.array([[1, 2, 3],
[4, 5, 6]])
np.concatenate([grid, grid])

خروجی کد بالا به شکل زیر خواهد بود

[[1 2 3]
 [4 5 6]
 [1 2 3]
 [4 5 6]]

همانطور که می‌بینیم این دو آرایه به شکل سطری به هم می چسبد ولی اگر بخواهیم به صورت ستونی به هم بچسبد باید مشخص کنیم که ترکیب آرایه ها بر اساس کدام بعد باشد که این بعد به طور پیشفرض اندیس صفر است و اگر بخواهیم ترکیب بر اساس بعد دوم باشد باید کد را به شکل زیر تغییر دهیم.

np.concatenate([grid, grid], axis=1)

یک نوع ترکیب دیگر وجود دارد به نام stack کردن که دو نوع عمودی و افقی دارد. برای مثال اگر بخواهیم که یک آرایه یک بعدی را با یک آرایه دوبعدی ترکیب کنیم از تابع vstack استفاده می‌کنیم مانند مثال زیر

x = np.array([1, 2, 3])
grid = np.array([[9, 8, 7],
[6, 5, 4]])
np.vstack([x, grid])

که خروجی به حالت زیر خواهد شد

 [[1, 2, 3],
[9, 8, 7],
[6, 5, 4]]  

و اگر بخواهیم دو آرایه را به صورت افقی ترکیب کنیم از تابع hstack به شکل زیر استفاده می کنیم.

y = np.array([[99],
[99]])
np.hstack([grid, y])

که خروجی به شکل زیر است

[[ 9  8  7 99]
 [ 6  5  4 99]]

جدا کردن آرایه ها

برعکس ترکیب کردن آرایه ها جدا کردن آرایه ها است. در جدا کردن‌آرایه ها یک آرایه به چند آرایه جدا تقسیم می شود. توابع جدا کردن split, vsplit, hsplit است.
برای مثال تابع split یک آرایه و یک بازه می‌گیرد و آرایه را طبق آن بازه به چند آرایه تقسیم می‌کند مثل کد زیر

x = [1, 2, 3, 99, 99, 3, 2, 1]
x1, x2, x3 = np.split(x, [3, 5])
print(x1, x2, x3)

نتیجه به شکل زیر است

[1 2 3] [99 99] [3 2 1]

همچنین در ادامه مثال‌هایی برای vsplit, hsplit آورده ایم.

grid = np.arange(16).reshape((4, 4))
upper, lower = np.vsplit(grid, [2])
print(upper)
print(lower)

که خروجی دو آرایه به شکل‌های زیر است


[[0 1 2 3]
[4 5 6 7]]


[[ 8 9 10 11]
[12 13 14 15]]



left, right = np.hsplit(grid, [2])
print(left)
print(right)

که خروجی به شکل‌های زیر است.

[[ 0 1]
[ 4 5]
[ 8 9]
[12 13]]

[[ 2 3]
[ 6 7]
[10 11]
[14 15]]


دقت داشته باشید که عملیاتی که با کمک numpy انجام می‌شود چندین برابر سریع‌تر از این است که بخواهیم آن‌ها را با استفاده از حلقه ها انجام دهیم.


مهدی عادلی فر
مهدی عادلی فر

بنیانگذار توسینسو و برنامه نویس

مهدی عادلی، بنیان گذار TOSINSO. کارشناس ارشد نرم افزار کامپیوتر از دانشگاه صنعتی امیرکبیر و #C و جاوا و اندروید کار می کنم. در زمینه های موبایل و وب و ویندوز فعالیت دارم و به طراحی نرم افزار و اصول مهندسی نرم افزار علاقه مندم.

نظرات