آموزش

متد ()apply. در Pandas: چه‌کار می‌کنه، کجا به درد می‌خوره و جایگزین‌های سریع‌ترش چی هستن

با متد ()apply. در Pandas آشنا می‌شی و یاد می‌گیری چطور از اون برای پردازش داده‌های دیتافریم استفاده کنی. همچنین یاد می‌گیری چطور با استفاده از تابع ()apply. عملیات موردنظر رو روی سطرها یا ستون‌های یک دیتافریم اجرا کنی.

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

خیلی‌ها برای اینکه از حلقه‌ها دوری کنن، سراغ .apply() می‌رن و انتظار دارن که سریع و بی‌دردسر باشه. در عمل، استفاده از .apply(axis=1) روی سطرها، هنوز هم یک حلقه در سطح پایتون محسوب می‌شه. این کار می‌تونه روی داده‌های بزرگ کُند باشه و گاهی اوقات نتایجی رو برگردونه که اصلا انتظارش رو نداشتی. راه‌حل ساده‌ست: برای کارهای رایج از عملیات برداری در pandas و numpy استفاده کن و .apply() رو فقط برای منطقی نگه دار که واقعا به چند ستون نیاز داره.

این راهنما نشون می‌ده که .apply() چطور کار می‌کنه، به اشتباهات رایج اشاره می‌کنه و الگوهای جایگزینی رو ارائه می‌ده که سریع‌تر و واضح‌ترن.

متدهای ()DataFrame.apply و ()Series.apply چی هستن؟

به‌طور پیش‌فرض، DataFrame.apply(func, axis=0) تابع func رو روی هر ستون اجرا می‌کنه. اگر axis=1 باشه، تابع روی هر سطر اجرا می‌شه. Series.apply(func)  معمولاً تابع func رو روی هر عنصر سری اعمال می‌کنه.

  • سطری یا ستونی: axis=1 یعنی «برای هر سطر» و axis=0 (حالت پیش‌فرض) یعنی «برای هر ستون».
  • اگر تابع یک لیست یا آرایه برگردونه، بسته به مقدار result_type، خروجی می‌تونه به چند ستون گسترش پیدا کنه یا به‌صورت یک سری از لیست‌ها برگرده. همچنین اگر طول لیست‌های برگردونده‌شده یکسان نباشه، نسخه‌های جدید pandas خطا ایجاد می‌کنن.

بیشتر کارهایی که شامل ترکیب یا تغییر ستون‌ها می‌شن، با استفاده از عبارت‌های برداری یا متدهای داخلی سریع‌تر و واضح‌ترن. مثال زیر تفاضل امتیازات یک تیم بیسبال رو بدون استفاده از .apply() محاسبه می‌کنه.

استفاده سطری از ()apply. وقتی واقعا بهش نیاز داری

فقط زمانی از .apply(axis=1) استفاده کن که منطق کدت واقعا به چند ستون وابسته‌ست و به‌راحتی نمی‌تونه به شکل برداری نوشته بشه (مثلا قوانین شرطی که به چندین فیلد بستگی دارن).

محاسبه یک مقدار استخراج‌شده از چند ستون

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

اگر تابعت فقط با داده‌های عددی کار می‌کنه و به آرایه‌های خام نیاز داره، می‌تونی raw=True رو تنظیم کنی. در این حالت، به‌جای اشیای pandas، یک آرایه numpy به تابع ارسال می‌شه و بخشی از سربار پردازشی pandas حذف می‌شه؛ در نتیجه اجرای کد می‌تونه سریع‌تر باشه.

یک بار ورودی تابع رو بررسی کن

وقتی یک تابع سطری جدید می‌نویسم، اول یک سطر رو چاپ می‌کنم تا مطمئن بشم دقیقا چه چیزی داره به تابع ارسال می‌شه.

مطالعه موردی: مجموع‌ها، جمع کل فصل و فِلَگ‌های متنی

با توجه به آمارهای سالانه تیم Rays، تا جایی که ممکنه سعی کن به‌جای .apply() از متدهای داخلی و ابزارهای عنصر به عنصر استفاده کنی.

به دست آوردن مجموع ستون‌ها به شکل بهینه

به‌جای .apply(sum)  از DataFrame.sum() استفاده کن. هم سریع‌تره و هم واضح‌تر.

محاسبه کل امتیازات کسب‌شده در یک فصل

برای این کار از محاسبات برداری بین ستون‌ها استفاده کن؛ نیازی به .apply() نداری.

تبدیل مقادیر 0 و 1 به متن

برای تغییرات عنصر به عنصر روی یک ستون، بهتره از Series.map() یا replace() استفاده کنی.

کنترل ساختار خروجی در ()apply.

وقتی تابع برای هر سطر بیشتر از یک مقدار برمی‌گردونه، بهتره ساختار خروجی رو دقیق مشخص کنی. این کار کمک می‌کنه خروجی غیرمنتظره نگیری و در نسخه‌های بعدی pandas هم کدت دچار مشکل نشه.

برگردوندن چند مقدار در قالب ستون‌های جداگانه

از result_type='expand' استفاده کن تا مقادیر موجود در یک لیست یا آرایه به چند ستون جداگانه تبدیل بشن.

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

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

نکات مهم برای بالا بردن کارایی

استفاده از .apply(axis=1) برای پیمایش سطری راحته، ولی روی دیتافریم‌های بزرگ خیلی کنده چون تابع تو رو به ازای هر سطر یک بار فراخوانی می‌کنه. الگوهای زیر بهت کمک می‌کنن تا از کند شدن برنامه‌ت دوری کنی.

  • از توابع و عملیات برداری در pandas و numpy و متدهای داخلی مثل sum، mean، clip، where، astype و متدهای مربوط به رشته‌ها استفاده کن.
  • اگر عملیات عددی روی سطرها یا ستون‌ها انجام می‌دی و تابعت می‌تونه با آرایه‌ها کار کنه، raw=True رو تنظیم کن تا یک آرایه numpy دریافت کنه و بخشی از سربار پردازشی pandas حذف بشه.
  • برای پردازش عنصر‌ به‌ عنصر روی یک ستون، به‌جای DataFrame.apply(axis=1) از Series.map() یا متدهای برداری استفاده کن.
  • از تغییر دادن مستقیم سطر یا ستونی که به تابع ارسال شده خودداری کن. به‌جاش مقدار جدید رو برگردون.

نکات مربوط به نسخه‌ها که باید بدونی (Pandas نسخه‌های ۲.x)

نسخه‌های اخیر pandas رفتار سخت‌گیرانه‌تری روی .apply() اعمال کردن تا خروجی‌ها قابل‌پیش‌بینی‌تر باشن.

  • برگردوندن مقادیر از نوع لیست: در نسخه‌های ۲.۰ به بالا، اگر طول لیست‌ها با هم مطابقت نداشته باشن برنامه خطا می‌ده. از طول‌های یکسان استفاده کن و وقتی چند ستون مختلف می‌خوای، result_type='expand' رو تنظیم کن.
  • بسط دادن خروجی: برگردوندن یک سری یا دیکشنری، مقادیر رو به یک دیتافریم با کلیدهای نام‌برده به عنوان نام ستون، بسط می‌ده (تثبیت‌شده در نسخه ۰.۲۳).
  • تغییرات Series.apply(): آرگومان convert_dtype منسوخ شده. اگر به انواع داده‌های مختلط نیاز داری، اول اون رو به نوع object تبدیل کن (برای مثال s.astype("object").apply(fn)). نسخه‌های جدیدتر بهت اجازه می‌دن تا مشخص کنی تابع fn تو مقادیر ساده دریافت می‌کنه یا خودش رو با یک سری در شرایط بیشتری وفق می‌ده.

متد ()apply. در مقایسه با ()map. و ()applymap. و ()agg.

متدی رو انتخاب کن که با نوع پردازش و ساختار داده‌‌ت هماهنگ باشه.

  • Series.map(func_or_dict):
    پردازش عنصر‌ به‌ عنصر روی یک ستون. برای جایگزینی مقادیر، نگاشت داده‌ها یا اجرای توابع ساده روی یک ستون، بهترین انتخابه.
  • DataFrame.apply(func, axis=1):
    برای منطق سطری؛ زمانی که پردازش به چند ستون به‌طور هم‌زمان نیاز داره.
  • DataFrame.apply(func, axis=0):
    برای منطق ستونی؛ در این حالت هر ورودی یک سریه که یک ستون رو نمایش می‌ده.
  • DataFrame.applymap(func):
    تابع رو روی تک‌تک سلول‌های دیتافریم اجرا می‌کنه. تا حد امکان کمتر ازش استفاده کن؛ چون روش‌های برداری معمولاً سریع‌ترن.
  • .agg() و .transform():
    برای محاسبات تجمیعی و پردازش‌های گروهی طراحی شدن. در زنجیره‌های groupby معمولاً این متدها انتخاب مناسب‌تری هستن.

اشتباهات رایج

موارد زیر مشکلاتی هستن که معمولا باعث می‌شن نتایج اشتباه بگیری یا سرعت اجرا پایین بیاد؛ مسیر اصلاح اون‌ها هم در ادامه توضیح داده شده.

  • فراموش کردن axis=1 برای عملیات سطر‌به‌سطر: اگر تابعت به‌جای هر سطر، هر ستون رو دریافت می‌کنه، احتمالاً یادت رفته axis=1 رو مشخص کنی. مقدار پیش‌فرض axis=0 هست و باعث می‌شه تابع روی ستون‌ها اجرا بشه.
  • دریافت غیرمنتظره یک سری از لیست‌ها: وقتی می‌خوای از هر سطر یک لیست یا آرایه برگردونی، result_type='expand' رو تعیین کن تا به ستون‌های مجزا تبدیل بشن.
  • پردازش کند کدهای سطری: کدها رو با دستورات برداری و توابع داخلی جایگزین کن؛ اگر این کار امکان‌پذیر نبود، برای پایین آوردن هزینه‌های پردازشی اضافه، متغیر raw=True رو در نظر بگیر.
  • تغییر داده‌های سطر ورودی: ورودی‌ها رو به‌صورت فقط‌خواندنی فرض کن و به‌جای تغییر دادن، مقادیر جدید رو برگردون.
  • تغییرات در نوع‌داده: اگر تابعت بعضی از اوقات مقادیر غیرصحیحی برمی‌گردونه، ستون‌هایی با نوع داده عدد صحیح می‌تونن تغییر کنن و به عدد اعشاری یا یک object تبدیل بشن. پس از این کار، در صورت نیاز با استفاده از متد astype نوع داده‌ها رو اصلاح کن.

نتیجه‌گیری

متد .apply() یک ابزار انعطاف‌پذیره، اما راه میان‌بری برای افزایش کارایی نیست. برای کارهای ریاضی، تجمیع‌ها، و تغییرات عنصر به‌ عنصر در یک ستون، کلا از توابع برداری استفاده کن. فقط زمانی سراغ DataFrame.apply(axis=1) برو که منطق برنامه‌ت واقعا در هر سطر نیاز به چند ستون داشته باشه. در جاهایی هم که واقعا لازم بود ازش استفاده کنی، حتما شکل خروجی رو با result_type تنظیم کن؛ واسه توابع عددی حتما گزینه raw=True رو در نظر داشته باش، و به انواع داده‌ها یا همون dtypes هم دقت کن. پیاده‌سازی این الگوها، در نسخه‌های جدید pandas باعث تولید نتایج قابل پیش‌بینی می‌شن و با بزرگ‌تر شدن داده‌هات توانایی مقیاس‌پذیری بالایی رو نشون می‌دن.

اشتراک‌گذاری
فهرست مطالب
  • متدهای ()DataFrame.apply و ()Series.apply چی هستن؟
  • انتخاب اول: عملیات برداری
  • استفاده سطری از ()apply. وقتی واقعا بهش نیاز داری
  • مطالعه موردی: مجموع‌ها، جمع کل فصل و فِلَگ‌های متنی
  • کنترل ساختار خروجی در ()apply.
  • نکات مهم برای بالا بردن کارایی
  • نکات مربوط به نسخه‌ها که باید بدونی (Pandas نسخه‌های ۲.x)
  • متد ()apply. در مقایسه با ()map. و ()applymap. و ()agg.
  • اشتباهات رایج
  • نتیجه‌گیری

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

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