برای مشاهده یافته ها از کلید Enter و برای خروج از کلید Esc استفاده کنید.

عبارت های کنترلی : بخش نخست

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

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

test_var <- 90
if (test_var < 100) {
+ print(paste(test_var, "is less than 100"))}

# [1] "90 is less than 100"

##############

test_var2 <- 150
if (test_var2 < 100) {
+ print(paste(test_var2, "is less than 100"))
+ } else {
+ print(paste(test_var2, "is greater than 100"))}

# [1] "150 is greater than 100"

##############

test_var3 <- 347
if (test_var2 < test_var3) {
+ print(paste(test_var2, "is less than", test_var3))
+ } else if (test_var2 == test_var3){
+ print(paste(test_var2, "and", test_var3, "are equal" ))
+ } else {
+ print(paste(test_var2, "is greater than", test_var3))}

# [1] "150 is less than 347"

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

علاوه بر ساختار معروف و کلاسیک if…else که در تمامی زبان های برنامه نویسی وجود دارد، تابع ()ifelse در زبان R امکان قابل توجهی را ارائه می کند. این تابع سه پارامتر را به این ترتیب می پذیرد: پارامتر نخست آزمون یا شرطی است که قرار است صحت آن بررسی شود، پارامتر دوم مقداری (مقادیری) است که در صورت صحیح (برقرار بودن) شرط به عنوان خروجی برگردانده می شود و پارامتر سوم هم مقداری (مقادیری) است که در صورت عدم برقرار بودن شرط اولیه به عنوان خروجی درنظر گرفته می شود.

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

همچنین، در موارد بررسی برقراری شرط برای دو بردار، اگر طول یکی از بردارها کوچکتر از بردار دیگر باشد، همانند نمونه هایی که در بخش بردارها بررسی کردیم، مقایسه مقادیر به اندازه طول بردار کوچکتر انجام شده و این روال به اندازه طول بردار بزرگتر، تکرار می شود. مثال های زیر، کاربرد تابع ()ifelse را نشان می دهد.

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

lang <- "R"
test_lang <- ifelse(lang == "R", "Good", "NotGood")
print(test_lang)
# [1] "Good"

##############


var_1 <- c(10,20,30,40)
var_2 <- c(30,70,12,94)
test_vec <- ifelse(var_1 > var_2, var_1, var_2)
print(test_vec)
# [1] 30 70 30 94

var_3 <- c(37)
test_vec2 <- ifelse(var_3 > var_2, var_3, var_2)
print(test_vec2)
# [1] 37 70 37 94

var_4 <- c(19,26)
test_vec3 <- ifelse(var_4 > var_2, var_4, var_2)
print(test_vec3)
# [1] 30 70 19 94

حلقه for را می توان شناخته شده ترین روش برای انجام عملیات تکراری (مانند بررسی عناصر یک لیست یا دیتافریم و انجام عملیاتی مشخص بر روی آن ها) بر روی داده است. در مثال های زیر مشاهده خواهید کرد که در هنگام استفاده از حلقه for در زبان R چگونه می توان به وسیله دستور append خروجی های هر گذر (iteration) را به خروجی قبلی اضافه کرد و در قالب یک بردار (و سایر حالت های ممکن) نمایش داد.

for (i in 1390:1402){
+ year_count <- paste("The year is", i)
+ print(year_count)}

#[1] "The year is 1390"
#[1] "The year is 1391"
#[1] "The year is 1392"
#[1] "The year is 1393"
#[1] "The year is 1394"
#[1] "The year is 1395"
#[1] "The year is 1396"
#[1] "The year is 1397"
#[1] "The year is 1398"
#[1] "The year is 1399"
#[1] "The year is 1400"
#[1] "The year is 1401"
#[1] "The year is 1402"

###############

var_year <- NULL

for (i in 1397:1402){
+ recent_year <- paste("The year is", i)
+ var_year <- append(var_year, recent_year)}

# [1] "The year is 1397" "The year is 1398" "The year is 1399" "The year is 1400" 
# [5] "The year is 1401" "The year is 1402"

به عنوان یک نکته تکمیلی و مهم درباره کارایی استفاده از حلقه ها در زبان R باید توجه داشته باشیم که این زبان در موارد مواجهه با رشد اشیا داده ای (data objects)، مانند مواردی که توسط یک حلقه for قصد محاسبه یا ذخیره مجموعه ای از آیتم های داده ای را به شیوه افزایشی داریم، کارایی خوبی ندارد. برای رفع این نقیصه که بیشتر در مواردی که با داده های بسیار زیاد رو به رو می شویم رخ می دهد، می توان در ابتدا یک ساختمان داده، مثلا یک بردار، به اندازه (طول) داده های مورد نظر ایجاد کرد و سپس از آن برای ذخیره کردن داده ها استفاده کرد. با اینحال، اگرچه این روش هم چندان قابلیت مقیاس پذیری ندارد ولی در مواردی می تواند مفید باشد.

یک نمونه از بهره گیری از چنین رویکردی را در مثال زیر مشاهده می کنید.

var_year <- vector(mode = "numeric", length = 7)
counter <- 1

for (i in 1397:1402){
        recent_year <- paste("The year is", i)
        var_year [counter] <- recent_year
        counter <- counter + 1
}

# [1] "The year is 1397" "The year is 1398" "The year is 1399" "The year is 1400" 
# [5] "The year is 1401" "The year is 1402"