افزایش سرعت کد Pandas به میزان ۱۰ برابر — از صفر تا صد
پانداز (pandas) یک ابزار شگفتانگیز در زمینه علوم داده محسوب میشود. این ابزار ساختار دیتافریم را در اختیار ما قرار میدهد که قابلیتهای محاسباتی قدرتمندی دارد و این کار را در قالب کاربرپسندی انجام میدهد. پانداز مستنداتی با کیفیت و پشتیبانی خوبی نیز دارد که موجب شده یادگیری آن آسان باشد. در این راهنما با روشهای مختلف افزایش ۱۰ برابری سرعت کد Pandas به میزان 10 آشنا میشویم.
یکی از مشکلات پانداز این است که گاهی اوقات کُند عمل میکند. این حالت در اغلب محاسباتی که قرار است انجام دهیم یک معضل به حساب میآید. اگر متد پردازشی کند باشد، اجرای برنامه زمان زیادی طول میکشد. در صورتی که میلیونها محاسبه مورد نیاز باشند، زمان محاسباتی به میزان زیادی افزایش مییابد.
این حالت یک مشکل رایج محسوب میشود. برخی اوقات لازم است. برای نمونه فرض کنید در حال طراحی مدلهای شبیهسازی برای بازنمایی تجهیزات رایج در ساختمانها هستیم. این بدان معنی است که تابعهایی برای تقلید فرایندهای انتقال حرارت و تصمیمهای منطق کنترل در یک قطعه سختافزاری طراحی میکنیم و سپس دادههایی که شرایط ساختمان و گزینههای رفتار دستگاه را در آن مدلها توصیف میکنند، ارسال میکنیم. در ادامه این مدلها میتوانند توضیح دهند که چه نوع تجهیزات نیاز داریم و به چه میزان نیازهای ما را برآورده میسازند و چه مقدار انرژی مصرف میشود.
به این منظور باید مدلها بر پایه زمان باشند. ما باید بتوانیم آن چه را در یک موقعیت زمانی در شبیهسازی رخ میدهد محاسبه کنیم و تنها آن زمان است که به بقیه محاسبه حرکت میکنیم. دلیل این مسئله آن است که خروجی یک مرحله به عنوان ورودی مرحله بعدی استفاده میشود. برای مثال فرض کنید دما را بخواهید در هر لحظه در یک کوره محاسبه کنید. آیا در حال حاضر روشن است؟ از دقیقه پیش تاکنون چه مقدار دما بالاتر رفته است؟ در آن زمان دما چه مقدار بود؟
این وابستگی به دفعات پیش یک مشکل ایجاد میکند. ما دیگر نمیتوانیم از محاسبات برداری استفاده کنیم. در این حالت حلقههای for کاملاً کند هستند.
برای سریعتر شدن محاسبات چه میتوان کرد؟
یک راهحل چه محاسبات برداری ممکن باشد و چه نباشد، این است که محاسبات را به Numpy تبدیل کنیم. بر اساس مستندات، Numpy در پسزمینه بسیاری از محاسبات را با استفاده از کد C که از پیش کامپایل شده اجرا میکند. این کد C از پیش کامپایل شده موجب میشود که پانداز با رد شدن از گام کنونی کامپایل و با گنجاندن بهینهسازیهای سرعت از پیش برنامهنویسی شده، بسیار سریعتر عمل کند. به علاوه Numpy اطلاعات زیادی در پانداز دارد. پانداز سوابق انواع داده و اندیسها را حفظ میکند و به اجرای بررسی خطا میپردازد. همه این موارد بسیار مفید هستند، اما در این زمان چندان ضرورتی ندارند و محاسبات را کند میکنند. Numpy این کارها را انجام نمیدهد و میتواند محاسبات را به مقدار زیادی سریعتر اجرا کند.
چندین روش برای تبدیل دادههای Pandas به Numpy وجود دارد. یک سری را میتوان با استفاده از متد .value تبدیل کرد. بدین ترتیب همان سری در Numpy ایجاد میشود. به عنوان یک مثال ساده به کد زیر توجه کنید:
import pandas as pd Series_Pandas = pd.Series(data=[1, 2, 3, 4, 5, 6]) Series_Numpy = Series_Pandas.values
یک دیتافریم را میتوان با استفاده از تابع ()to_numpy. تبدیل کرد. بدین ترتیب یک شیء int64 با همان مقادیر در Numpy ایجاد میشود. توجه کنید که بدین ترتیب نام ستونها حفظ نمیشود و باید یک دیکشنری ایجاد کنید که نامهای ستونهای پانداز را به شمارههای ستون Numpy تبدیل میکند. این کار با کدی مانند زیر قابل اجرا است:
import pandas as pd import numpy as np Dataframe_Pandas = pd.DataFrame(data=[[0,1], [2,3], [4,5]], columns = ['First Column', 'Second Column']) Dataframe_Numpy = Dataframe_Pandas.to_numpy() Column_Index_Dictionary = dict(zip(Dataframe_Pandas.columns, list(range(0,len(Dataframe_Pandas.columns)))))
این کد دیتافریم را به شیء int64 در Numpy تبدیل میکند و همه ابزارهای مورد نیاز برای تکرار روی هر خط، ویرایش مقادیر در ستونهای خاص را به روشی کاربرپسند ارائه میکند. هر سلول را میتوان به روشی مشابه استفاده از تابع loc. پانداز با اندیس گذاری Numpy و با پیروی از الگوی زیر فراخوانی کرد:
int64object[row, Dictionary[‘Pandas Column Name’]]
برای نمونه اگر بخواهیم مقدار ردیف نخست Second Column را روی 9 تنظیم کنیم، میتوانیم از کد زیر استفاده کنیم:
Dataframe_Numpy[0, Column_Index_Dictionary['Second Column']] = 9
کد چقدر سریعتر میشود؟
میزان سریعتر شدن کد در این حالت بسته به شرایط مختلف اندازه متفاوتی میتواند داشته باشد. برخی اسکریپتها با سوئیچ به Numpy نسبت به بقیه بهبود بیشتری نشان میدهند. همه چیز به نوع محاسبات مورد استفاده از اسکریپت و درصد همه محاسباتی که به Numpy تبدیل میشوند بستگی دارد. اما در هر صورت نتیجه میتواند چشمگیر باشد.
برای مثال در مورد یکی از مدلهای شبیهسازی که در ابتدای مقاله صحبتش کردیم با تغییر از مبنای پانداز به Numpy، شاهد کاهش زمان شبیهسازی از 362 ثانیه به 32 ثانیه بودیم. این مقدار 9% زمان اولیه است. یعنی بیش از 10 برابر کدمان سریعتر اجرا شده است.
سخن پایانی
Numpy همه ظرفیتهای محاسباتی Pandas را دارد، اما آنها را بدون اطلاعات سربار و با بهرهگیری از متدهای از پیش کامپایل شده و بهینهسازی شده اجرا میکند. در نتیجه میتواند بسیار سریعتر از Pandas باشد.
تبدیل یک دیتافریم از Pandas به Numpy کاری نسبتاً سرراست محسوب میشود. امکان استفاده از تابع ()to_numpy. در دیتافریم ها برای تبدیل خودکار آنها وجود دارد و سپس یک دیکشنری از نامهای ستون ایجاد میشود تا بتوانیم به هر سلول مشابه تابع loc. پانداز دسترسی داشته باشیم.
این تغییر ساده میتواند نتایج چشمگیری در پی داشته باشد. اسکریپتی که از ()to_numpy. استفاده میکند، میتواند یکدهم زمان مورد نیاز برای اجرا در پانداز را نیاز داشته باشد.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی پایتون
- مجموعه آموزشهای برنامهنویسی
- آموزش الگوهای طراحی (Design Patterns) در پایتون (Python)
- برترین ویژگی های Pandas 1.0 — راهنمای کاربردی
- دیتافریم (DataFrame) در کتابخانه Pandas— راهنمای مقدماتی
==