آموزش

آموزش آرایه numpy در پایتون

در این آموزش مقدماتی numpy، یاد می‌گیریم چطور یک آرایه numpy ایجاد کنیم، از قابلیت broadcasting استفاده کنیم، به مقادیر آرایه دسترسی داشته باشیم، آرایه‌ها ر, تغییر بدیم و پردازش کنیم و با قابلیت‌های کاربردی دیگر این کتابخونه آشنا بشیم.

تاریخ انتشار:
24 تیر 1405
پایتون
15 دقیقه
علم داده
تحلیل داده
کاربرهای فینکا در چه شرکت‌هایی مشغول به کار هستند؟

همون‌طور که می‌دونی، کتابخونه numpy هم مثل scipy، scikit-Learn، pandas و بقیه پکیج‌های مشابهه. وقتی داری علم داده یاد می‌گیری، اصلاً نباید این پکیج‌های پایتون رو از دست بدی؛ مهم‌ترین دلیلش هم اینه که این کتابخونه یه ساختار داده آرایه‌ای بهت می‌ده که نسبت به لیست‌های پایتون مزایای زیادی داره. مثلاً فشرده‌تره، خوندن و نوشتن آیتم‌ها توش سریع‌تره و کلاً کار باهاش راحت‌تر و بهینه‌تره.

این آموزش numpy هم دقیقاً روی همین موضوع تمرکز داره. اینجا نه‌تنها می‌فهمی آرایه‌های numpy دقیقاً چی هستن و چطور باید پایتون رو نصب کنی، بلکه یاد می‌گیری چطور آرایه بسازی (حتی وقتایی که داده‌هات از فایل خونده می‌شن)، مکانیزم broadcasting چطور کار می‌کنه، چطور می‌تونی راهنمایی بگیری، چطوری آرایه‌هات رو تغییر بدی و در نهایت چطور اون‌ها رو به تصویر بکشی (مصورسازی کنی).

اگه دوست داری درباره آرایه‌های numpy و بقیه ساختارهای داده‌ای که تو مسیر علم داده به دردت می‌خورن بیشتر بدونی، پیشنهاد می‌کنیم یه سر به دوره مقدمه‌ای بر پایتون برای علم داده تو سایت فینکا بزنی؛ اونجا یه فصل کامل فقط به numpy اختصاص داده شده.

آرایه numpy تو پایتون چیه؟

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

همون‌طور که از اسمش مشخصه، آرایه numpy ساختار داده اصلی کتابخونه numpy به حساب میاد. اسم این کتابخونه هم مخفف Numeric Python یا Numerical Python هست.

به عبارت دیگه، numpy یه کتابخونه پایتونه که تو محاسبات علمی کاربرد خیلی مهمی داره. این کتابخونه یه مجموعه کامل از ابزارها و تکنیک‌هاست که می‌تونی ازشون برای حل مدل‌های ریاضی تو مسائل علوم و مهندسی استفاده کنی.

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

اما اصلاً خود آرایه چیه؟

وقتی به خروجی چاپ‌شده چند تا آرایه نگاه می‌کنی، می‌تونی اون رو مثل یه شبکه ببینی که مقادیری از یه نوع مشخص رو تو خودش جا داده:

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

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

  • اشاره‌گر داده، آدرس حافظه اولین بایت توی آرایه رو نشون می‌ده.
  • اشاره‌گر نوع داده، نوع عناصری که داخل آرایه قرار دارن رو توصیف می‌کنه.
  • شکل، در واقع فرم و ابعاد آرایه رو مشخص می‌کنه.
  • گام‌ها تعداد بایت‌هایی هستن که باید تو حافظه رد بشن تا به عنصر بعدی برسیم. اگه گام‌های تو (10,1) باشن، باید ۱ بایت بری جلو تا به ستون بعدی برسی و ۱۰ بایت بری جلو تا سطر بعدی رو پیدا کنی.

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

خب، تئوری دیگه کافیه. بیا خودمون این موضوع رو عملی بررسی کنیم:

می‌تونی این موارد رو با بررسی ویژگی‌های آرایه numpy خیلی راحت تست کنی:

می‌بینی که حالا اطلاعات خیلی بیشتری به دست آوردی: مثلاً نوع داده‌ای که چاپ می‌شه int64 یا int32 هست؛ این خیلی دقیق‌تره! این یعنی آرایه تو قالب ۶۴ بایت تو حافظه ذخیره می‌شه (چون هر عدد صحیح ۸ بایت فضا می‌گیره و تو یه آرایه با ۸ تا عدد صحیح داری). گام‌های آرایه بهمون می‌گن که باید ۸ بایت (یک مقدار) رو رد کنی تا به ستون بعدی بری، اما ۳۲ بایت (۴ مقدار) رو باید رد کنی تا به همون موقعیت تو سطر بعدی برسی. به همین دلیله که گام‌های آرایه به صورت (32,8) نشون داده می‌شن.

دقت کن که اگه نوع داده رو روی int32 تنظیم کنی، تاپل گام‌هایی که برمی‌گرده (16, 4) می‌شه؛ چون هنوز هم باید یه مقدار بری جلو تا به ستون بعدی برسی و ۴ مقدار تا به همون موقعیت تو سطر پایین‌تر برسی. تنها چیزی که فرق می‌کنه اینه که هر عدد صحیح به جای ۸ بایت، حالا ۴ بایت فضا اشغال می‌کنه.

آرایه‌ای که این بالا می‌بینی، همون‌طور که از اسمش پیداست، یه آرایه دوبعدیه: یعنی سطر و ستون داره. سطرها رو با axis=0 می‌شناسن، در حالی که ستون‌ها axis=1 هستن. شماره محور با توجه به تعداد ابعاد می‌ره بالا: تو آرایه‌های سه‌بعدی (که تو کد قبلی یه مثال ازش دیدی)، یه axis=2 اضافی هم داری. حواست باشه که این محورها فقط برای آرایه‌هایی که حداقل ۲ بُعد دارن معنی می‌ده، چون داشتن محور برای آرایه‌های یک‌بعدی کلاً کاربردی نداره.

این محورها بعداً وقتی که می‌خوای شکل آرایه‌های numpy خودت رو تغییر بدی، حسابی به کارت میان.

چطوری numpy رو نصب کنیم؟

قبل از اینکه بتونی خودت این آرایه‌های numpy رو امتحان کنی، اول باید مطمئن بشی که اون رو روی سیستم خودت نصب کردی (با این فرض که داری روی سیستم شخصی خودت کار می‌کنی). اگه این کتابخونه رو از قبل داری، می‌تونی کلاً از این بخش بگذری :)

ولی اگه هنوز باید محیط کاریت رو آماده کنی، خوبه بدونی که دو تا راه اصلی برای نصب numpy روی سیستم وجود داره: با کمک Python wheels یا توزیع پایتون Anaconda.

نصب با استفاده از Python Wheels

اول مطمئن شو که خود پایتون رو نصب کردی. اگه هنوز این کار رو نکردی، می‌تونی به راهنمای نحوه نصب پایتون ما یه نگاهی بندازی :)

اگه داری رو ویندوز کار می‌کنی، یادت نره که پایتون رو به متغیر محیطی PATH اضافه کنی. بعدش، حتماً یه پکیج‌منیجر مثل pip نصب کن تا خیالت راحت بشه که می‌تونی از کتابخونه‌های منبع‌باز پایتون استفاده کنی.

خبر خوب اینه که نسخه‌های اخیر پایتون ۳ به صورت پیش‌فرض pip رو دارن، پس یه دور چک کن ببین داریش یا نه. اگه داشتی، قبل از نصب numpy حتماً آپدیتش کن:

فایل wheel مناسب numpy رو برای سیستم خودت از وب‌سایت PyPI دانلود کن. می‌تونی لیست فایل‌های wheel در دسترس numpy رو تو Python Package Index پیدا کنی.
 
وقتی فایل wheel مربوط به numpy رو دانلود کردی، با استفاده از خط فرمان (Command Prompt) یا ترمینال برو به دایرکتوری‌ای که فایل اونجا ذخیره شده.
 
حالا numpy رو با دستور زیر نصب کن، فقط یادت باشه نام فایل wheel دانلودشده رو به جای numpy--.whl قرار بدی:

مثلاً، اگه نسخه 1.20.3 از numpy رو برای یه سیستم ویندوز ۶۴ بیتی دانلود کرده باشی، دستورت به این شکل درمیاد:

وقتی نصب تموم شد، می‌تونی مفسر پایتون رو باز کنی و با اجرای دستور زیر مطمئن بشی که numpy به‌درستی نصب شده:

اگه هیچ پیام خطایی ندیدی، یعنی numpy با موفقیت نصب شده و آماده استفاده‌ست!

نصب با توزیع پایتون Anaconda

برای نصب numpy، می‌تونی توزیع پایتون Anaconda رو دانلود کنی. این روش خیلی راحته و بهت اجازه می‌ده سریعاً کارتو شروع کنی! اگه هنوز دانلودش نکردی، برو به صفحه رسمیش و بگیرش. دستورالعمل‌های نصب رو دنبال کن و حالا برای استفاده آماده‌ست!

شاید برات سوال پیش بیاد که چرا این روش راحت‌تره؟

خوبی این توزیع پایتون اینه که دیگه نیازی نیست نگران نصب جداگانه numpy یا بقیه پکیج‌های اصلی تحلیل داده (مثل pandas، scikit-learn و غیره) باشی.

مخصوصاً اگه تازه با پایتون، برنامه‌نویسی یا ترمینال آشنا شدی، این خیلی عالیه که Anaconda از قبل ۱۰۰ تا از محبوب‌ترین پکیج‌های علم داده برای پایتون، R و Scala رو تو خودش داره. ولی حتی برای متخصصای باتجربه‌تر هم، Anaconda سریع‌ترین راه برای شروع پروژه‌های علم داده‌ست.

علاوه بر این، Anaconda چند تا محیط توسعه منبع‌باز مثل ژوپیتر و Spyder رو هم شامل می‌شه. اگه دوست داری بعد از این آموزش با ژوپیتر نوب‌بوک کار کنی، یه سر به آموزش Jupyter notebook تو سایت فینکا بزن.

خلاصه که برای شروع کار با numpy و بقیه پکیج‌های علم داده، دانلود Anaconda یه گزینه عالیه!

چطوری آرایه‌های numpy بسازیم؟

خب، حالا که محیط کارت رو آماده کردی، وقت کارهای عملیه. البته که قبلاً با آرایه‌ها تو کدهای بالا یه آشنایی مختصری پیدا کردی، ولی تا الان واقعاً خودت دست به کد نشدی، چون اول باید numpy رو روی سیستمت نصب می‌کردی. حالا که این کار انجام شده، وقتشه ببینی برای اجرای کدهای بالا خودت دقیقاً باید چیکار کنی.

برای ساخت یه آرایه numpy، می‌تونی خیلی راحت از تابع np.array() استفاده کنی. تنها کاری که باید بکنی اینه که یه لیست بهش پاس بدی و اگه خواستی، نوع داده رو هم مشخص کنی. اگه می‌خوای درباره انواع داده‌هایی که می‌تونی انتخاب کنی بیشتر بدونی، به این راهنما سر بزن یا یه نگاهی به تقلب‌نامه numpy فینکا بنداز.

اگه تازه‌کاری، اصلاً نیازی نیست بری این نوع داده‌های numpy رو حفظ کنی، اما مهمه که بدونی داری با چه داده‌ای کار می‌کنی. تعیین نوع داده بیشتر برای وقتاییه که نیاز داری کنترل دقیقی روی نحوه ذخیره داده‌هات تو حافظه داشته باشی؛ مخصوصاً وقتی با داده‌های حجیم کار می‌کنی، خیلی به دردت می‌خوره.

یادت نره برای کار با تابع np.array()، اول باید مطمئن بشی که کتابخونه numpy رو وارد کردی.

کتابخونه numpy یه قرارداد نانوشته داره: وقتی می‌خوای واردش کنی، بهتره با نام مستعار np این کار رو بکنی. این‌طوری خیالت راحته که بقیه برنامه‌نویس‌ها کدت رو خیلی راحت‌تر می‌خونن و متوجه می‌شن.

تو مثال زیر، همون آرایه my_array رو می‌سازی که قبلاً دیدیش:

اگه دوست داری درباره نحوه ساخت لیست‌ها تو پایتون بیشتر بدونی، پیشنهاد می‌کنیم به آموزش سوالات متداول لیست پایتون ما سر بزنی.

البته گاهی اوقات از قبل نمی‌دونی چه داده‌ای قراره تو آرایه‌ت قرار بگیره، یا اینکه می‌خوای داده‌ها رو از یه منبع دیگه وارد آرایه numpy کنی. تو این شرایط، می‌تونی از توابعی استفاده کنی که یه آرایه اولیه (با مقادیر پیش‌فرض) برات می‌سازن یا داده‌ها رو از فایل‌های متنی بارگذاری می‌کنن.

تو بخش‌های بعدی یاد می‌گیری که چطور این کارها رو انجام بدی.

چطوری یه آرایه «خالی» تو numpy بسازیم؟

معمولاً وقتی برنامه‌نویس‌ها می‌گن می‌خوان آرایه «خالی» بسازن، منظورشون اینه که یه ساختار اولیه و موقت داشته باشن تا بعداً بتونن مقدارها رو توش پر کنن. می‌تونی آرایه‌ها رو با یک‌ها (ones) یا صفرها (zeros) مقداردهی اولیه کنی، یا آرایه‌هایی بسازی که با مقادیر با فاصله مساوی، مقادیر ثابت یا حتی اعداد تصادفی پر می‌شن.

البته می‌تونی یه آرایه کاملاً خالی هم بسازی.

خوشبختانه numpy توابع زیادی برای همه این کارها داره.

می‌تونی همه اینا رو تو ادیتور زیر امتحان کنی!

نکته: با توابع بالا کمی تمرین کن تا کار باهاشون رو یادبگیری!

  • برای بعضی توابع مثل np.ones()، np.random.random()، np.empty()، np.full() یا np.zeros() تنها کاری که باید بکنی اینه که شکل آرایه‌ای رو که می‌خوای، بهشون پاس بدی. به عنوان یه گزینه اختیاری برای np.ones() و np.zeros()، می‌تونی نوع داده رو هم مشخص کنی. در مورد np.full()، باید اون مقدار ثابتی رو که می‌خوای تو کل آرایه تکرار بشه هم وارد کنی.
  • با np.linspace() و np.arange() می‌تونی آرایه‌هایی از مقادیر با فاصله‌های مساوی بسازی. فرق این دو تا تابع تو اینه که مقدار سومی که بهشون پاس می‌دی، برای np.linspace() نشون‌دهنده تعداد نمونه‌هاست و برای np.arange() نشون‌دهنده مقدار گام. یعنی تو اولی می‌گی مثلاً یه آرایه ۹تایی می‌خوام که اعدادش بین ۰ و ۲ باشن. ولی تو دومی مشخص می‌کنی که آرایه از ۱۰ شروع بشه و با گام‌های ۵تایی بره جلو.

یادت باشه که numpy با توابع np.eye() و np.identity() بهت اجازه می‌ده یه آرایه یا همون ماتریس همانی (Identity Matrix) بسازی. ماتریس همانی یه ماتریس مربعیه که تمام عناصر قطر اصلی اون یک و بقیه عناصرش صفرن. وقتی یه ماتریس رو تو یه ماتریس همانی ضرب می‌کنی، ماتریس اصلیت تغییری نمی‌کنه.

به عبارت دیگه، طبق قوانین ضرب ماتریس‌ها، اگه یه ماتریس رو تو ماتریس همانی ضرب کنی، حاصلش می‌شه دقیقاً همون ماتریس اولیه.

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

چطوری آرایه‌های numpy رو از روی متن بارگذاری کنیم؟

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

با چیزهایی که تا اینجا یاد گرفتی، خیلی نمی‌تونی رو داده‌های واقعی کار کنی. پس باید از یه سری توابع خاص مثل loadtxt() یا genfromtxt() برای خوندن داده‌ها از فایلت استفاده کنی.

فرض کن یه فایل متنی به اسم data.txt داریم و می‌خوایم با استفاده از numpy مقادیر هر ستونش رو بخونیم.

تو کد بالا، از loadtxt() برای بارگذاری داده‌ها استفاده کردی. همون‌طور که می‌بینی، اولین آرگومانی که تابع می‌گیره، همون فایل متنی data.txt هست. در ادامه هم یه سری آرگومان خاص وجود داره: تو این دستور، سطر اول رو نادیده گرفتی (چون احتمالاً هدر بوده) و با unpack=TRUE ستون‌ها رو به شکل آرایه‌های مجزا برگردوندی. این یعنی مقادیر ستون Value1 رفتن تو متغیر x، و بقیه ستون‌ها هم به همین ترتیب.

دقت کن که اگه داده‌هات با کاما از هم جدا شدن (مثل فایل‌های CSV) یا می‌خوای نوع داده رو دقیق مشخص کنی، می‌تونی آرگومان‌های delimiter و dtype رو هم به loadtxt() اضافه کنی.

خیلی راحت و سرراست بود، نه؟

حالا بیا یه نگاهی به فایل دوم بندازیم:

اینجا می‌بینی که برای بارگذاری داده‌ها رفتیم سراغ genfromtxt(). دلیلش اینه که تو این فایل یه سری مقادیر گمشده داریم که با رشته 'MISSING' مشخص شدن و باید مدیریت‌شون کنیم.

چون تابع genfromtxt() رشته‌های متنی رو توی ستون‌های عددی به مقدار nan تبدیل می‌کنه، می‌تونی با مشخص کردن آرگومان filling_values، این مقادیر رو به هر عدد دیگه‌ای که دوست داری تغییر بدی. تو این مثال، تصمیم گرفتیم مقادیر گمشده رو با 999- جایگزین کنیم.

اگه احیاناً مقادیری داری که genfromtxt() نمی‌تونه اونا رو به nan تبدیل کنه، همیشه می‌تونی از آرگومان missing_values استفاده کنی تا صریحاً بهش بگی مقادیر گمشده داده‌هات دقیقاً چی هستن.

البته این تمام ماجرا نیست.

نکته: یه سر به داکیومنت numpy.genfromtxt بزن تا ببینی چه آرگومان‌های دیگه‌ای رو می‌تونی اضافه کنی تا داده‌هات دقیقاً همون‌طوری که می‌خوای وارد بشن.

حالا شاید برات سوال بشه که تفاوت اصلی بین این دو تا تابع چیه.

احتمالاً از مثال‌ها متوجه شدی، ولی به طور کلی، genfromtxt() انعطاف‌پذیری بیشتری بهت می‌ده و از loadtxt() قوی‌تره.

اگه بخوایم عملی‌تر بگیم: تابع loadtxt() فقط زمانی کار می‌کنه که همه سطرهای فایل متنی تعداد مقادیر یکسانی داشته باشن. به همین خاطر وقتی می‌خوای با مقادیر گمشده کار کنی، معمولاً استفاده از genfromtxt() خیلی راحت‌تره.

ولی این قطعاً تنها دلیلش نیست.

اگه یه نگاه گذرا به لیست آرگومان‌های genfromtxt() بندازی، می‌بینی که تنظیمات خیلی بیشتری برای وارد کردن داده‌ها در اختیارت می‌ذاره؛ مثلاً می‌تونی حداکثر تعداد سطرهایی که باید خونده بشن رو مشخص کنی یا ازش بخوای فاصله‌های خالی رو به طور خودکار حذف کنه.

چطوری آرایه‌های numpy رو ذخیره کنیم؟

وقتی کارت با آرایه‌ها تموم شد، می‌تونی اون‌ها رو تو یه فایل ذخیره کنی. اگه می‌خوای آرایه رو تو یه فایل متنی ذخیره کنی، می‌تونی خیلی راحت از تابع savetxt() استفاده کنی:

یادت نره که np.arange() یه آرایه numpy با مقادیر دارای فواصل مساوی ایجاد می‌کنه و مقدار سومی که به این تابع می‌دی، همون مقدار گام (step) هست.

البته راه‌های دیگه‌ای هم برای ذخیره آرایه‌ها وجود داره. اگه می‌خوای داده‌هات رو تو فایل‌های باینری یا به صورت آرشیو ذخیره کنی، یه نگاه به توابع جدول زیر بنداز:

save() آرایه رو تو یه فایل باینری با فرمت .npy ذخیره می‌کنه
savez() چندین آرایه رو تو یه آرشیو .npz (غیرفشرده) ذخیره می‌کنه
savez_compressed() چندین آرایه رو تو یه آرشیو .npz (فشرده) ذخیره می‌کنه

برای اطلاعات بیشتر یا دیدن مثال‌هایی از اینکه چطور می‌تونی از این توابع استفاده کنی، می‌تونی به این صفحه راهنمای numpy سر بزنی، یا از توابع راهنمای خود numpy استفاده کنی تا سریعاً جواب سوالت رو بگیری!

نمی‌دونی این توابع راهنمای numpy دقیقاً چی هستن؟

نگران نباش! تو بخش‌های بعدی درباره‌شون بیشتر یاد می‌گیری.

چطوری آرایه‌های numpy رو بررسی کنیم؟

علاوه بر ویژگی‌هایی که قبلاً گفتیم (یعنی data، shape، dtype و strides)، موارد دیگه‌ای هم هستن که می‌تونی ازشون استفاده کنی تا خیلی راحت اطلاعات بیشتری درباره آرایه‌ت به دست بیاری. اونایی که برای شروع ممکنه برات جذاب‌تر باشن، این مواردن:

اینا تقریباً همه ویژگی‌هایی هستن که یه آرایه می‌تونه داشته باشه.

اگه حس می‌کنی الان همه‌شون برات کاربردی نیستن، اصلاً نگران نباش. این کاملاً طبیعیه؛ چون همون‌طور که تو بخش‌های قبلی خوندیم، فقط زمانی باید نگران حافظه و این جزئیات باشی که داری با دیتاست‌های خیلی بزرگ کار می‌کنی.

راستی، یادت باشه که علاوه بر این ویژگی‌ها، راه‌های دیگه‌ای هم داری که بتونی اطلاعات بیشتری بگیری یا حتی آرایه‌ت رو یه کم تغییر بدی:

حالا که آرایه‌ت رو ساختی (چه دستی با np.array()، چه با توابع اولیه، و چه با بارگذاری داده‌ها از طریق loadtxt() یا genfromtxt())، وقتشه بریم سراغ ویژگی کلیدی دیگه‌ای که کتابخونه numpy رو این‌قدر مهم کرده: محاسبات علمی.

Broadcasting تو numpy چطوری کار می‌کنه؟

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

تصویر زیر یه نمونه از نحوه کار broadcasting رو تو numpy نشون می‌ده: 

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

برای این کار، تو از مکانیزم broadcasting استفاده می‌کنی.

البته یه سری قوانین هم داره. ولی قبل از اینکه ناامید بشی، باید بگم این قوانین خیلی ساده و سرراست هستن!

  • اول از همه، برای اینکه broadcasting درست انجام بشه، ابعاد آرایه‌هات باید با هم سازگار باشن. دو بُعد، زمانی با هم سازگارن که دقیقاً برابر باشن. مثال زیر رو ببین:

دو بُعد تو حالتی که یکیشون برابر ۱ باشه هم سازگار محسوب می‌شن:

حواست باشه که اگه ابعاد سازگار نباشن، با خطای ValueError مواجه می‌شی.

نکته: حتماً اندازه آرایه خروجی رو هم بعد از محاسبات چک کن! می‌بینی که اندازه‌اش در واقع همون بیشترین مقدار تو هر بُعد از آرایه‌های ورودیته.

یعنی می‌بینی که نتیجه x-y یه آرایه با شکل (3,4) بهت می‌ده: y شکلش (4,) بود و x شکلش (3,4). برای ساختن شکل آرایه جدید، بزرگ‌ترین اندازه تو هر بُعد از x و y در نظر گرفته شده.

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

می‌بینی که، با وجود اینکه به نظر می‌رسه x و y ابعاد متفاوتی دارن، بازم می‌تونن با هم جمع بشن.

دلیلش اینه که تو همه ابعاد با هم سازگارن:

  • آرایه x ابعادش ۳ در ۴ هست.
  • آرایه y ابعادش ۵ در ۱ در ۴ هست.

از اونجایی که بالاتر دیدیم اگه یکی از ابعاد ۱ باشه بازم سازگاری برقراره، می‌بینی که این دو تا آرایه واقعاً گزینه‌های خیلی خوبی برای broadcasting هستن!

چیزی که اتفاق می‌افته اینه که تو بُعدی که اندازه y یکه و آرایه دیگه اندازه‌اش بزرگ‌تر از یکه (یعنی ۳)، آرایه اول طوری رفتار می‌کنه که انگار تو طول اون بُعد کپی شده.

یادت نره که شکل آرایه حاصل، بازم بیشترین اندازه تو هر بُعد از x و y می‌شه: یعنی ابعاد خروجی برابر (5,3,4) درمیاد.

خلاصه بگم، اگه می‌خوای از broadcasting استفاده کنی، باید خیلی حواست به شکل و ابعاد آرایه‌هات باشه.

ولی اگه ابعاد سازگار نبودن چی؟

اگه برابر نبودن یا هیچ‌کدومشون هم ۱ نبود چیکار کنیم؟

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

ریاضیات آرایه چطوری کار می‌کنه؟

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

پس احتمالاً تعجب نمی‌کنی اگه بگیم می‌تونی خیلی راحت از +، -، *، / یا % برای جمع، تفریق، ضرب، تقسیم یا محاسبه باقیمانده دو (یا چند) تا آرایه استفاده کنی. با این حال، یکی از دلایل اصلی محبوبیت numpy اینه که خودش توابع اختصاصی برای این کارها داره. توابع معادل این عملگرهایی که دیدی، به ترتیب np.add()، np.subtract()، np.multiply()، np.divide() و np.remainder() هستن.

همین‌طور می‌تونی با np.exp() و np.sqrt() آرایه‌ها رو به توان برسونی یا ازشون جذر بگیری، یا سینوس و کسینوس آرایه‌ت رو با np.sin() و np.cos() حساب کنی. در نهایت، بد نیست بدونی که با np.log() می‌تونی لگاریتم طبیعی بگیری یا با dot() ضرب داخلی آرایه‌ت رو محاسبه کنی.

همه اینا رو می‌تونی تو کد زیر تست کنی.

فقط یادت باشه: اول چک کن ببین چه آرایه‌هایی برای این تمرین بارگذاری شدن!

یادت میاد broadcasting چطور کار می‌کرد؟ خودت ابعاد و شکل متغیرهای x و y رو بررسی کن. ببین قوانین broadcasting رعایت شدن یا نه؟

البته توابع ریاضی numpy به همینا ختم نمی‌شه.

یه نگاه به این لیست کوچیک از توابع تجمعی بنداز:

a.sum() جمع کل عناصر آرایه
a.min() کوچک‌ترین مقدار آرایه
b.max(axis=0) بزرگ‌ترین مقدار یه ردیف از آرایه
b.cumsum(axis=1) مجموع تجمعی عناصر
a.mean() میانگین
b.median() میانه
a.corrcoef() ضریب همبستگی
np.std(b) انحراف معیار

علاوه بر اینا، مکانیزم‌هایی هم هستن که بهت اجازه می‌دن عناصر آرایه‌ها رو با هم مقایسه کنی. مثلاً اگه بخوای چک کنی که آیا عناصر دو تا آرایه دقیقاً یکسانن یا نه، از عملگر == استفاده می‌کنی. برای بررسی بزرگ‌تر یا کوچک‌تر بودن عناصر هم عملگرهای < یا > به کارت میان.

خیلی ساده به نظر می‌رسه، درسته؟

خبر خوب اینه که می‌تونی کل آرایه‌ها رو هم یک‌جا با هم مقایسه کنی! برای این کار، باید از تابع np.array_equal() استفاده کنی. فقط کافیه دو تا آرایه‌ای رو که می‌خوای مقایسه بشن بهش پاس بدی.

دقت کن که علاوه بر مقایسه، می‌تونی عملیات منطقی رو هم روی آرایه‌ها انجام بدی. توابعی مثل np.logical_or()، np.logical_not() و np.logical_and() برای همین کارن و دقیقاً مثل همون عملگرهای منطقی رایج OR، NOT و AND کار می‌کنن.

تو ساده‌ترین حالت، از OR استفاده می‌کنی تا ببینی آیا عناصرت یکسانن (مثلاً جفتشون ۱ باشن) یا اینکه حداقل یکی از دو عنصر ۱ هست. اگه جفتشون ۰ باشن، خروجی FALSE می‌ده. از AND استفاده می‌کنی تا چک کنی که عنصر دومت هم ۱ هست، و از NOT استفاده می‌کنی تا ببینی عنصر دومت با ۱ فرق داره یا نه.

بیا اینا رو تو قطعه کد زیر تست کنیم:

چطوری آرایه‌ها رو زیرمجموعه‌گیری، برش و اندیس‌گذاری کنیم؟

علاوه بر عملیات ریاضی، ممکنه گاهی اوقات بخوای فقط یه بخش از آرایه اصلی (یا آرایه خروجیت) یا فقط چند تا عنصر خاصش رو برداری و تو تحلیل‌های بعدی ازش استفاده کنی. تو این شرایط، باید آرایه‌هات رو زیرمجموعه‌گیری(subsetting) ، برش (slice) و اندیس‌گذاری (indexing) کنی.

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

اگه اصلاً نمی‌دونی این عملیات‌ها چطوری انجام می‌شن، فعلاً کافیه همین دو تا نکته اساسی رو یادت باشه:

  • از براکت‌ها [] به عنوان عملگر اندیس استفاده می‌کنی.
  • معمولاً یه سری عدد صحیح به این براکت‌ها می‌دی، ولی می‌تونی از علامت دونقطه (:) یا ترکیبی از : و اعداد استفاده کنی تا دقیقاً مشخص کنی کدوم عنصرها، ردیف‌ها یا ستون‌ها رو می‌خوای جدا کنی.

زیرمجموعه‌گیری

جدای از این دو تا نکته، بهترین راه برای اینکه ببینی این موارد چطوری با هم کار می‌کنن اینه که چند تا مثال از عملیات زیرمجموعه‌گیری رو با هم بررسی کنیم:

خروجی
2
خروجی
7
7
خروجی
11

برش دادن

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

می‌تونی تفاوتش رو تو مثال‌های کد زیر ببینی:

خروجی
[1 2]
خروجی
[2 6]
خروجی
[[ 1  2  3  4]
 [ 9 10 11 12]]

به طور کلی، این قواعد تو برش دادن صدق می‌کنن:

تو کدهای بالا، هر آرایه به صورت جداگانه مقداردهی اولیه می‌شه و زیرمجموعه‌ها تو بلوک‌های کد مجزا چاپ می‌شن. my_array، my_2d_array و my_3d_array به ترتیب همون آرایه‌های یک‌بعدی، دوبعدی و سه‌بعدی هستن و با استفاده از قواعد اندیس‌گذاری چاپ می‌شن.

تو مثال اول، از برش استفاده می‌کنیم تا آیتم‌های اندیس ۰ و ۱ رو از my_array جدا کنیم. تو مثال دوم، مقادیر ردیف ۰ و ۱ و ستون ۱ رو از my_2d_array می‌کشیم بیرون. تو مثال سوم هم از نماد ... کمک می‌گیریم تا تمام عناصر تو امتداد بُعدهای اول و دوم، و دومین عنصر رو تو امتداد بُعد سوم از my_3d_array انتخاب کنیم.

اندیس‌گذاری

در نهایت می‌رسیم به بحث اندیس‌گذاری. وقتی پای numpy در میون باشه، ما با دو نوع اندیس‌گذاری سروکار داریم: اندیس‌گذاری بولین و اندیس‌گذاری پیشرفته (که بهش fancy indexing هم می‌گن).

(اگه برات سواله که این اسم دومی از کجا اومده، باید بگیم که این یه اصطلاح کاملاً رایج تو numpy هست!)

اولی اندیس‌گذاری بولینه. تو این روش، به جای اینکه عناصر رو بر اساس شماره اندیس انتخاب کنی، مقادیری رو جدا می‌کنی که یه شرط خاص رو برآورده کنن.

نوشتنش تو کد هم خیلی راحته:

حواست باشه که برای نوشتن شرط می‌تونی از عملگرهای منطقی | و & هم استفاده کنی. اگه بخوای شرط بالا رو با این عملگرها بنویسی (که البته یه کم ناکارآمده)، کدت این‌شکلی می‌شه: bigger_than_3 = (my_3d_array > 3) | (my_3d_array == 3).

با آرایه‌هایی که ما الان ساختیم شاید خیلی جای مانور نباشه، اما رو آرایه‌هایی که مثلاً شامل اسامی یا شهرها هستن، کارهایی که می‌تونی بکنی بی‌نهایته!

اما برسیم به اندیس‌گذاری پیشرفته؛ کاری که اینجا انجام می‌دی اینه: یه لیست یا یه آرایه از اعداد صحیح رو به عنوان ورودی می‌دی تا مشخص کنی کدوم ردیف‌ها و با چه ترتیبی از آرایه اصلی جدا بشن.

به نظرت یه کم انتزاعی و پیچیده میاد؟

نگران نباش، فقط کافیه تو قطعه کد پایین خودت امتحانش کنی:

احتمالاً تو نگاه اول، خط دوم کد برات یکم عجیب به نظر برسه. این کاملاً طبیعیه. اگه کد رو بخش‌بخش کنی، بهتر متوجه می‌شی چی به چیه:

    • اگه فقط my_2d_array[[1,0,1,0]] رو اجرا کنی، نتیجه این‌طوری می‌شه:
    • کاری که بخش دوم، یعنی [:,[0,1,2,0]] انجام می‌ده اینه: به پایتون می‌گی می‌خوای همه ردیف‌های این نتیجه رو نگه داری، ولی می‌خوای ترتیب ستون‌ها رو یه کم عوض کنی. دلت می‌خواد ستون‌های ۰، ۱ و ۲ دقیقاً همون‌طوری که هستن بمونن، ولی به جای اینکه ستون ۳ رو نشون بده، همون ستون ۰ رو به عنوان ستون آخر تکرار کنه. این کار همچین نتیجه‌ای بهت می‌ده:

دیگه کاملاً مشخصه که اندیس‌گذاری پیشرفته برات هیچ رمزی نداره!

چطوری راهنمایی بگیریم؟

به عنوان یه نکته جانبی، باید بدونی که همیشه می‌تونی درباره ماژول‌ها، توابع یا کلاس‌هایی که داری باهاشون کار می‌کنی اطلاعات بیشتری بگیری. مخصوصاً اوایل کار با numpy که ممکنه همه‌چی یه کم سنگین به نظر برسه.

راهنمایی گرفتن خیلی راحته.

فقط کافیه از تابع کمک‌کننده‌ای که numpy تو دل خودش داره استفاده کنی:

  • برای توضیحات سریع و دیدن کدهای نمونه مرتبط با توابع، کلاس‌ها یا ماژول‌ها، می‌تونی از info() استفاده کنی. اگه از اون آدمایی هستی که با مثال و انجام دادن یاد می‌گیرن، این دقیقاً همون چیزیه که بهش نیاز داری! تنها چالشی که ممکنه موقع استفاده از این تابع داشته باشی اینه که باید حتماً بدونی صفات یا توابعی که دنبالشونی، تو کدوم ماژول قرار دارن. اگه دقیق متوجه منظورم نشدی، مثال کد زیر رو ببین.

حتماً تو قطعه کد زیر امتحانشون کن!

همون‌طور که می‌بینی، واقعاً باید بدونی که dtype ویژگی مربوط به ndarray هست. تازه یادت نره که قبل از ماژول‌ها، کلاس‌ها یا هر چیزی که دربارش اطلاعات می‌خوای، حتماً np رو بذاری، وگرنه با یه خطایی شبیه به این مواجه می‌شی:

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

نه اینکه نتونی خودت از پسش بربیای، اصلاً منظور این نیست!

ولی بعضی از این توابع ممکنه برات سوال ایجاد کنن. مثلاً تفاوت دقیق بین تغییر اندازه (resizing) و تغییر شکل (reshaping) چیه؟

یا روی هم چیدن (stacking) افقی و عمودی آرایه‌ها چه فرقی با هم دارن؟

بخش بعدی دقیقاً برای جواب دادن به همین سوالاست، ولی هر جا حس کردی شک داری، خیالت راحت باشه که می‌تونی از همین توابع کمکی استفاده کنی تا سریعاً قضیه برات روشن بشه.

چطوری آرایه‌ها رو تغییر بدیم؟

انجام عملیات ریاضی روی آرایه‌ها کاریه که قراره زیاد باهاش درگیر بشی، اما چیزی که از این‌ها و کار با broadcasting هم مهم‌تره، اینه که یاد بگیری چطوری آرایه‌هات رو تغییر بدی.

در ادامه چند تا از رایج‌ترین تغییراتی رو که ممکنه رو آرایه‌هات انجام بدی با هم می‌بینیم.

چطوری آرایه‌ها رو ترانهاده کنیم؟

کاری که ترانهاده (transpose) کردن با آرایه‌ها می‌کنه اینه که جای ابعادشون رو عوض می‌کنه. به زبون ساده‌تر، شکل آرایه رو جابه‌جا می‌کنی. بیا با یه مثال کوچیک، تأثیر ترانهاده کردن رو ببینیم:

نکته: اگه تغییر ظاهری بین آرایه اصلی و نسخه transpoe شده اون خیلی برات واضح نیست، می‌تونی شکل هر دو آرایه رو چک کنی تا ببینی دقیقاً چطور ابعاد جابه‌جا شدن.

همون‌طور که دیدی، دو تا روش برای transpoe کردن وجود داره. هر دو یه کار رو انجام می‌دن و فرق خاصی با هم ندارن. فقط باید یادت باشه که T بیشتر شبیه یه میانبره، ولی np.transpose() انعطاف‌پذیری خیلی بیشتری بهت می‌ده. به همین خاطر، اگه می‌خوای از آرگومان‌های بیشتری استفاده کنی، بهتره بری سراغ این تابع.

transpoe کردن آرایه‌های دوبعدی و سه‌بعدی خیلی خوب جواب می‌ده، اما وقتی فقط یه آرایه یک‌بعدی داری چه اتفاقی می‌افته؟ فکر می‌کنی تغییری می‌کنه؟

می‌تونی این رو تو قطعه کد پایین امتحان کنی. آرایه یک‌بعدی رو از قبل برات آماده کردیم:

کاملاً حق با توئه! وقتی یه آرایه یک‌بعدی رو ترانهاده می‌کنی، هیچ تغییری روش اعمال نمی‌شه!

مقایسه تغییر شکل و تغییر اندازه آرایه‌ها

احتمالاً در بخش مربوط به broadcasting خوندی که اگر بخوای عملیات محاسباتی روی آرایه‌ها انجام بدی، ابعاد اون‌ها باید با هم سازگار باشن. اما شاید این سؤال برات پیش اومده باشه که اگر ابعاد آرایه‌ها سازگار نباشن، باید چی کار کرد.

اینجاست که جواب سؤالت رو می‌گیری!

اگر آرایه‌ها ابعاد یکسان یا سازگاری نداشته باشن، یکی از راه‌حل‌ها اینه که اندازه آرایه رو تغییر بدی. برای این کار می‌تونی از تابع np.resize() استفاده کنی. این تابع یک آرایه جدید با شکلی که مشخص کردی برمی‌گردونه.

اگر آرایه اصلی و ابعاد جدید رو به np.resize() بدی و اندازه آرایه جدید از آرایه اصلی بزرگ‌تر باشه، numpy عناصر آرایه اصلی رو به‌صورت تکراری کپی می‌کنه تا آرایه جدید کاملاً پر بشه.

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

حالا با یک مثال، تفاوت این دو حالت رو بررسی می‌کنیم.

علاوه بر تغییر اندازه، می‌تونی شکل (Shape) آرایه‌ت رو هم تغییر بدی. این یعنی به آرایه یه فرم جدید می‌دی بدون اینکه داده‌های داخلش دست بخورن. نکته مهم تو تغییر شکل اینه که کل اندازه (تعداد عناصر) آرایه جدید نباید تغییری کنه. اگه همون آرایه x رو در نظر بگیریم (که اندازه‌اش ۳ در ۴ یا همون ۱۲ بود)، باید حواست باشه که آرایه جدیدت هم دقیقاً ۱۲ تا عنصر داشته باشه.

راستی... اگه خواستی اندازه یه آرایه رو تو کد چک کنی، حتماً از ویژگی size استفاده کن؛ مثل x.size یا x.reshape((2,6)).size:

اگه با این روش‌ها مشکلت حل نشد، می‌تونی یه آرایه رو به انتهای آرایه اصلیت بچسبونی، یا یه سری عناصر رو اضافه/حذف کنی تا ابعادت دقیقاً با اون یکی آرایه‌ای که قراره تو محاسبات شرکت کنه، هماهنگ بشه.

یه تابع دیگه هم هست که موقع تغییر شکل آرایه‌ها خیلی به دردت می‌خوره: ravel(). این تابع آرایه‌هات رو کاملاً مسطح (Flat) می‌کنه. یعنی اگه یه آرایه دوبعدی، سه‌بعدی یا چندبعدی داشته باشی، با این تابع می‌تونی همه‌شون رو صاف کنی و بریزی تو یه آرایه یک‌بعدی.

خیلی کاربردی به نظر میاد، مگه نه؟

چطوری آرایه‌ها رو به هم بچسبونیم؟

وقتی آرایه‌ها رو به آرایه اصلیت append می‌کنی، در واقع داری اون‌ها رو به انتهای آرایه اصلی اضافه می‌کنی. اگه می‌خوای این مقادیر رو جای دیگه‌ای غیر از انتهای آرایه بذاری، باید به جای append از insert استفاده کنی. اگه می‌خوای بیشتر در این باره بدونی، برو بخش بعدی.

به لطف numpy، اضافه کردن مقادیر به انتهای آرایه خیلی راحته؛ فقط کافیه از تابع np.append() استفاده کنی.

تو قطعه کد پایین می‌تونی ببینی چطور کار می‌کنه. یادت نره که هر وقت خواستی می‌تونی با تایپ کردن اسم آرایه‌ها (مثل my_array) چک کنی ببینی دقیقاً چه آرایه‌هایی بارگذاری شدن.

همون‌طور که دیدی، بعد از append کردن، هیچ تغییری تو خود my_array ایجاد نمی‌شه؛ چون np.append() به جای اینکه آرایه اصلی رو تغییر بده، یه آرایه کاملاً جدید برمی‌گردونه.

حالا بیا همینو رو my_2d_array تست کنیم:

دقت کن وقتی می‌خوای یه ستون اضافی به my_2d_array اضافه کنی، باید حتماً axis (محور) رو مشخص کنی. یادت باشه که تو آرایه‌های دوبعدی، axis=1 نشون‌دهنده ستون‌هاست و axis=0 سطرها رو مشخص می‌کنه.

چطوری عناصر رو تو آرایه درج یا حذف کنیم؟

علاوه بر append، می‌تونی عناصر جدید رو تو هر جای آرایه که خواستی درج (insert) کنی یا عناصر قبلی رو حذف (delete) کنی. احتمالاً خودت حدس زدی که توابع این کارها چی هستن: بله، np.insert() و np.delete().

چطوری آرایه‌ها رو با هم ترکیب یا از هم جدا کنیم؟

همچنین می‌تونی آرایه‌هات رو با هم ترکیب (join) کنی. برای این کار کلی تابع مختلف وجود داره که لیست مهم‌ترین‌هاشون رو در ادامه می‌بینی.

می‌تونی اینا رو تو کد امتحان کنی، ولی حتماً حواست به شکل و ابعاد آرایه‌ها باشه. آرایه‌هایی که برات بارگذاری شدن اینا هستن: x، my_array، my_resized_array و my_2d_array.

وقتی داری با این توابع کار می‌کنی، چند تا نکته مهمه که باید بهشون دقت کنی:

  • اگه می‌خوای با np.concatenate() دو تا آرایه رو به هم بچسبونی، باید حتماً تعداد ابعادشون یکی باشه. یعنی اگه می‌خوای یه آرایه رو به my_array (که یک‌بعدیه) وصل کنی، آرایه دومت هم باید یک‌بعدی باشه.
  • با np.vstack() می‌تونی خیلی راحت my_array رو با my_2d_array ترکیب کنی. فقط یادت باشه چون داری آرایه‌ها رو به صورت ردیفی روی هم می‌چینی، باید تعداد ستون‌هاشون دقیقاً یکی باشه. پس می‌تونی یه آرایه با شکل (2,4) یا (3,4) رو به my_2d_array اضافه کنی، به شرط اینکه جفتشون ۴ تا ستون داشته باشن. خلاصه بگم، آرایه‌ها باید تو همه ابعادشون، غیر از محور (axis) اول، شکل یکسانی داشته باشن. این قانون برای np.r_[] هم صدق می‌کنه.
  • برای np.hstack() باید مطمئن بشی که هم تعداد ابعاد برابره و هم تعداد ردیف‌ها تو هر دو آرایه یکسانه. یعنی می‌تونی آرایه‌هایی با شکل (2,3) یا (2,4) رو به my_2d_array (که شکلش (2,4) هست) بچسبونی. تا وقتی تعداد ردیف‌ها یکی باشه، همه‌چی درسته. با اینکه این تابع هنوز تو numpy کار می‌کنه، ولی بهتره به جاش از np.concatenate() یا np.stack() استفاده کنی.
  • وقتی از np.column_stack() استفاده می‌کنی، آرایه‌هات باید بُعد اولشون با هم برابر باشه. تو این مثال شکلشون یکیه، ولی حتی اگه my_resized_array شکلش (2,1) یا (2,) هم بود، بازم می‌شد اونا رو با موفقیت کنار هم قرار داد.
  • روش np.c_[] هم یکی دیگه از راه‌های ترکیب کردنه و اینجا هم دقیقاً مثل مورد قبلی، اولین بُعد هر دو آرایه باید با هم هم‌خونی داشته باشه.

حالا، همون‌طور که می‌تونی آرایه‌ها رو با هم ترکیب کنی، گاهی اوقات هم نیاز داری اونا رو از هم جدا (split) کنی. همون‌طور که می‌شد اونا رو افقی و عمودی به هم چسبوند، با توابع np.hsplit() و np.vsplit() می‌تونی اونا رو از هم جدا کنی:

مهم‌ترین چیزی که باید موقع استفاده از این دو تا تابع جداکننده حواست بهش باشه، شکل آرایه‌ته. بیا رو همون مثال بالا کار کنیم: شکل my_stacked_array الان (2,8) هست. اگه می‌خوای تعیین کنی از کدوم اندیس آرایه جدا بشه، باید حتماً این شکل و ابعاد رو تو ذهنت داشته باشی.

چطوری آرایه‌های numpy رو مصورسازی کنیم؟

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

مصورسازی با()np.histogram

شاید از اسمش این‌طور برداشت بشه، ولی تابع np.histogram() در واقع خود نمودار هیستوگرام رو برات رسم نمی‌کنه! کاری که می‌کنه اینه که می‌شماره تو هر بازه (bin) چند تا از عناصر آرایه‌ت قرار می‌گیرن. در واقع همین محاسباته که تعیین می‌کنه هر ستون از هیستوگرامت باید چقدر ارتفاع داشته باشه.

چیزی که تو به عنوان ورودی به np.histogram() می‌دی، در مرحله اول همون آرایه‌ایه که داری روش کار می‌کنی. موقع محاسبه، خود تابع آرایه‌ت رو به صورت موقت کاملاً مسطح می‌کنه.

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

اگه خودت بازه‌ها رو دستی تنظیم کنی، نتیجه یه کم فرق می‌کنه: دیگه خبری از اعداد اعشاری برای بازه‌ها نیست و فقط اعداد صحیح رو می‌بینی.

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

اما اصلاً محاسبه این اعداد چه فایده‌ای داره وقتی نتونیم نمودارش رو ببینیم؟

با کمک کتابخونه matplotlib، کشیدن نمودار مثل آب خوردنه! تازه نیازی هم نیست برای محاسبه هیستوگرام حتماً از np.histogram() استفاده کنی. وقتی داده‌هات (که مسطح شدن) و بازه‌ها رو مستقیم به تابع plt.hist() پاس بدی، خودش تمام محاسبات و رسم نمودار رو یه جا برات انجام می‌ده:

کد بالا یه هیستوگرام تر و تمیز مثل عکس زیر بهت می‌ده:

استفاده از ()np.meshgrid

یکی دیگه از راه‌های (البته غیرمستقیم) برای مصورسازی آرایه‌ها، استفاده از np.meshgrid() هست. چالشی که موقع رسم نمودار با آرایه‌ها داری اینه که برای مختصات x و y به آرایه‌های دوبعدی نیاز داری. با این تابع، می‌تونی یه شبکه مستطیلی از مقادیر x و y بسازی: تابع np.meshgrid() دو تا آرایه یک‌بعدی می‌گیره و دو تا ماتریس دوبعدی تحویلت می‌ده که شامل همه جفت‌های (x, y) ممکن از اون دو تا آرایه هستن. بعدش می‌تونی از این ماتریس‌ها برای رسم انواع مختلف نمودارها استفاده کنی.

استفاده از np.meshgrid() مخصوصاً وقتی می‌خوای توابع ریاضی رو روی یه شبکه گرافیکی پیاده کنی خیلی به کارت میاد، دقیقاً مثل چیزی که تو کد زیر می‌بینی:

فراتر از تحلیل داده با numpy

تبریک می‌گیم، بالاخره رسیدی به آخر آموزش numpy!

مسیر طولانی‌ای رو اومدی، پس حتماً وقت بذار و دانشی رو که تو این مدت به دست آوردی تمرین کن تا خوب تو ذهنت جا بیفته. یادت نره که نسخه مناسب خودت رو از چیت‌شیت numpy فینکا دانلود کنی تا تو پروژه‌هات دم دستت باشه و کارت رو راحت کنه!

حالا که تمام این تئوری‌ها رو یاد گرفتی، وقتشه که یه کم عملی‌تر با مفاهیم و تکنیک‌های این آموزش کار کنی. یکی از بهترین کارایی که می‌تونی بکنی اینه که بری سراغ آموزش scikit-learn و ببینی این آرایه‌ها چطوری تو ساخت مدل‌های یادگیری ماشین استفاده می‌شن.

اگه خیلی به یادگیری ماشین علاقه نداری، یه دور چک کن ببین Anaconda رو رو سیستمت نصب کردی یا نه. اگه آره، با کمک این راهنمای جامع ژوپیتر نوت‌بوک کار با آرایه‌های numpy رو تو محیط ژوپیتر شروع کن. همچنین پیشنهاد می‌کنیم یه نگاهی به این ژوپیتر نوت‌بوک هم بندازی؛ خیلی خوب بهت یاد می‌ده که چطور تو محیط تعاملی ژوپیتر با کمک numpy و چند تا کتابخونه دیگه، داده‌ها رو تحلیل کنی.

در نهایت، پیشنهاد می‌کنیم حتماً یه سر به دوره‌های فینکا تو زمینه تغییر و مصورسازی داده‌ها بزنی. دوره‌های تغییر دیتافریم با pandas و مبانی pandas ما گزینه‌های خیلی خوبی برای ادامه مسیرت هستن.

اشتراک‌گذاری
فهرست مطالب
  • آرایه numpy تو پایتون چیه؟
  • چطوری numpy رو نصب کنیم؟
  • چطوری آرایه‌های numpy بسازیم؟
  • Broadcasting تو numpy چطوری کار می‌کنه؟
  • ریاضیات آرایه چطوری کار می‌کنه؟
  • چطوری آرایه‌ها رو زیرمجموعه‌گیری، برش و اندیس‌گذاری کنیم؟
  • چطوری راهنمایی بگیریم؟
  • چطوری آرایه‌ها رو تغییر بدیم؟
  • چطوری آرایه‌های numpy رو مصورسازی کنیم؟
  • فراتر از تحلیل داده با numpy

دریافت اپلیکیشن فینکا

با اپلیکیشن فینکا، به بیشتر دوره‌ها و مسیرها روی موبایل دسترسی دارید، تمرین می‌کنید و یادگیری رو هم‌زمان روی موبایل و دسکتاپ ادامه می‌دید.