اگر مجموعه آموزشهای Rرا تا الآن با ما همراهی کرده باشید میتوانید اسکریپتهای مورد نیاز خود تست کنید و نتایج مورد نظر را بگیرید. دستوراتی که تا حالا اجرا میکردیم در خط فرمان Rبه راحتی قابل استفاده بودند اما زمانی که بخواهیم عملیات را تکرار کنیم به روش قبل سخت بوده بهتر است تحلیلها را دسته بندی کرده و آنها را در توابعی قرار میدهیم تا از این به بعد برای تکرار تحلیل مورد نظر فقط تابع را فراخوانی کنیم. البته اکثر دستوراتی که در قسمتهای پیشین استفاده میکردیم خود توابعی از پیش تعریف شده بودند.
خصوصیات توابع
• دارای اسم هستند.
• پارامتر ورودی میگیرند.
• عملیاتی را انجام میدهند.
• برای انجام عملیات بعدی میتوانند دارای مقدار برگشتی باشند.
• میتوانند شمال فراخوانی توابع دیگر باشند.
• یک برنامه مجموعهای از توابع است.
• توابع میتوانند برای استفاده مجدد نوشته شوند.
• و یک تابع خوب تایعی است که کاربرد عمومی داشته باشد، با دقت نوشته شده باشد و به خوبی مستند شده باشد.
نمونهای از یک تابع ساده
بهتر است نگاهی به کد یک تابع ساده بیندازیم و خروجی آن را ببینیم.
sin.plot <- function(period){ xvals <- seq(from = 0, to = 2 * pi, length = 100) yvals <- sin(xvals / period) plot(x = xvals, y = yvals, type = "l", lty = 1, xaxs = "i", lwd =2) } sin.plot(period = 1)
برای توضیح این کد به عکس زیر نگاه کنید و بر اساس شمارههای تعیین شده توضیحات را بخوانید.
1. نام تابع: نام تابع در تعریف توابع اولین آلمانی است که نوشته میشود. این نام میتواند شامل تمامی حروف الفبای انگلیسی اعم از بزرگ و کوچک، خط زیرین (underline) و نقطه باشد.
2. کلمه کلیدی function: همانند زبانهای برنامهنویسی دیگر در Rنیز کلمات کلیدی وجود دارد که functionیکی از آنهاست که در تعریف توابع باید حتماً حضور داشته باشد و پس از علامت انتساب نوشته میشود.
3. پارامتر: ورودیهای توابع در پرانتز بعد از کلمه کلیدی functionقرار میگیرند در صورتی که بیش از یکی باشند با کاما از هم جدا میشوند. نکته قابل توجه دیگری که وجود دارد در رابطه با پارمترها مقدار پیشفرض است. در صورتی که نیاز باشد در همین پرانتز پس از تعریف پارامتر میتواند از علامت مساوی و سپس مقدار پیشفرض استفاده کرد.
4. متغیرهای محلی: هر تابع دارای محدودهای است که با علامت آکلاد باز و بسته مشخص میشود. درون آکلاد باز و بسته بدنه تابع نامیده میشود و اگر متغیری در بدنه یک تابع تعریف شود متغیر محلی خوانده شده و در بیرون تابع قابل دسترسی نیست. البته اگر متغیری در حوزه جهانی یا بیرون از بدنه تمامی توابع تعریف شود در توابع میتوان از این متغیرها استفاده کرد که پیشنهاد نمیشود. اگر یک متغیر محلی همنام با متغیر جهانی وجود داشته باشد تابع از متغیر محلی استفاده میکند.
5. فراخوانی تابع seq: این تابع از توابع کتابخانه baseهست که به صورت ضمنی در تمامی اسکریپتها بارگذاری میشود. این تابع یک سری اعداد ایجاد میکند که از پارامتر fromشروع و به پارامتر toخاتمه مییابد. پارامتر lengthطول سری را تعیین میکند.
6. پلات: برای کشیدن نمودارها و بصریسازی از این تابع استفاده میشود که دو پارامتر xو yآن تعیین کننده مقادیر محورهای نمودار هستند.
7. پارامتر type: این پارمتر تعیین کننده نوع نقطه یا خط بودن است که lمشخص میکند که خط استفاده کند.
8. پارامتر lty: نوع خط را تعیین میکند که مقطع باشد یا ممتد.
9. پارامتر xaxs: برای این استفاده شده است که محدود نمودار کامل کشیده شود در صورتی که از rبه جای iاستفاده شود فقط تا قسمتی میکشد که مقدار xو yآن تعیین کرده باشد.
10. پارامتر lwd: میزان ضخامت خط را تعیین میکند.
11. فراخوانی تابعی که ایجاد کردهایم توسط نام آن و ارسال پارامتر به آن صورت میگیرد.
12. نتیجه نمودار تابع را در شکل ببینید.
نکته: در صورتی که در تعریف توابع نیاز به مقدار بازگشتی باشد، این مقدار بازگشتی را میتوان توسط نوشتن returnو نوشتن مقدار بازگشتی در پرانتز جلوی آن برگرداند.
return(out)
حلقهها
حلقهها در زبانهای مختلف کاربرد زیادی دارند. کاربرد آنها در انجام کارهای تکراری با تعداد مشخص است. حلقهها در Rبه صورت foreachدر زبانهای دیگر است. برای مثال فرض کنید میخواهیم اعداد فرد یک رقمی را چاپ کنیم. به صورت زیر عمل میکنیم.
for (i in 1:10) { if (!i %% 2){ next } print(i) }
همانطور که در قسمتهای گذشته بیان شد عبارت 1:10به معنی ایجاد وکتوری شامل اعداد یک تا ده است که سادهنویسی عبارت زیر است.
c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
علامت تعجب در عبارت ifبه معنی ضد یا خلاف (not) منطقی است. %% دو علامت درصد به معنی modاست. عبارت nextکاری همچون continueدر زبانهای دیگر دارد. به عبارت دیگر nextباعث میشود دستورات بعد از آن در حلقه اجرا نشوند و عدد بعدی چک شود.در کل معنی عبارت ifبه این صورت است:
اگر که باقیمانده تقسیم عدد iبر دو صفر شود عدد بعدی را چک کن و در غیر این صورت عدد را چاپ کن.
برای مثال دوم فرض کنید میخواهیم جذر اعداد موجود در یک وکتور را بگیریم و در همان وکتور بریزیم. این کار را توسط حلقه انجام میدهیم.
xs <- seq(1, 100, by = 2) print(xs) for (i in seq_along(xs)){ xs[i] <- sqrt(xs[i]) } print(xs)
تابع seqوکتوری میسازد از شروع آن با عدد یک است و عدد بعدی جمع عدد فعلی به علاوه دو میشود تا نهایتاً عدد آخر بزرگتر از صد نشود. در حلقه seq_alongتعداد اندیسهای وکتور را میدهد در نتیجه با اندیس Iمیتوان به درایههای وکتور دسترسی پیدا کرد. تابع sqrtنیز جذر عدد را حساب میکند.
شرطها
در برنامهها شرطها کاربرد بالایی دارند. همینطور که در مثالهای بالا نیز از شرط استفاده شده است. عبارت شرطی باید جوابی منطقی (trueیا false) داشته باشد. مثالهایی از انواع استفاده از این عبارات را در زیر مشاهده نمایید.
مقایسه تساوی مقدار xبا پنج if (x==5)
مقایسه تساوی مقدار xبا پنج و yبا هفت، بدنه شرط زمانی اجرا میشود که جواب هر دو مقایسه درست باشد
if (x==5 & y==7)
مقایسه بزرگتر یا مساوی بودن xاز پنجif (x>=5)
مقایسه تساوی xبا پنج و بزرگتر یا مساوی بودن yاز ۱۷، در صورتی بدنه شرط اجرا میشود که جواب یکی از این مقایسهها یا هر دو درست باشد.if (x==5 | y>=17)
مقایسه تساوی xبا یکی از مقادیری که در وکتور ارائه شده موجود باشدif (x %in% c(1,2,3,5))
خلاف مقدار منطقی foundدر صورتی بدنه شرط اجرا میشود که مقدار منطقیfoundنادرست باشدif (!found)
if (!is.na(x) & y==3)
در عبارت آخر is.naتعیین میکند که xمقدار گم شده (missing) است یا نه. یا به عبارت دیگر مقدار xقابل دسترس است یا خیر که جواب آن منطقی است که یا درست است یا نادرست.
ثبت نظر