R مجموعهای از عملگرها دارد که با بسیاری از زبانهای دیگر یکسان است:
1 == 2 # FALSE
1 != 2 # TRUE
1 < 2 # TRUE
1 > 2 # FALSE
1 <= 2 # TRUE
1 >= 2 # FALSE
شکل پایهای if-then-else این است:
if (x > 10) {
y <- "big"
} else if (x > 2) {
y <- "medium"
} else {
y <- "tiny"
}
در این حالت، هم پرانتزهای ( ) دور مقدار «منطقی» و هم آکولادهای { } دور بدنه الزامیاند.
یک دستور if ساده را میتوان کوتاه کرد:
if (x == 0) return("success")
با نگاهی به مفهوم vector-filtering که در ادامه میآید: عبارت شرطی داخل پرانتز () باید به یک TRUE/FALSE واحد ارزیابی شود.
گنجاندن بردارها در مقایسه معمولاً یک بردار از مقادیر منطقی به دست میدهد، بنابراین باید آنها را در یک تابع تجمیعکننده مانند all() (آیا همهی مقادیر TRUE هستند؟) یا any() (آیا حداقل یک مقدار TRUE است؟) پیچید.
numbers <- c(4,5,7,9,10,11)
numbers %% 3 == 0 # gives vector of booleans
#> [1] FALSE FALSE FALSE TRUE FALSE FALSE
# use any() to get a single TRUE/FALSE
if (any(numbers %% 3 == 0)) print("1 or more numbers are divisible by 3")
#> [1] "1 or more numbers are divisible by 3"
ifelse
شکل جایگزین if-else ممکن است مفید باشد، به شرط آنکه فقط یک نتیجهی «درست» یا «غلط» وجود داشته باشد.
y <- ifelse(x > 8, "big", "small")
# Don't mix result types:
z <- ifelse(x > 100, 100, "small") # numeric or string result? Expect problems!
ifelse() دقیقاً سه پارامتر میگیرد:
۱. عبارت منطقی
۲. مقدار در صورت TRUE بودن
۳. مقدار در صورت FALSE بودن.
ورودیهای برداری پذیرفته میشوند و در آن صورت خروجی هم برداری خواهد بود.
در این حالت، مطمئن شوید که هر دو شاخه به یک نوع داده منتهی میشوند: عددی، کاراکتری، منطقی و غیره.
این موضوع در مفهوم vector-functions پوشش داده خواهد شد.
دو نتیجه (در مثال بالا "big", "small") باید مقادیر واحدی باشند.
متأسفانه، دادن یک بردار بلندتر در اینجا احتمالاً باعث میشود R کاری گیجکننده و غیرمنتظره انجام دهد، بدون آنکه پیام هشداری بدهد.
if_else
نگهدارندگان زبان R سیاستی دارند مبنی بر پرهیز از تغییرات ناسازگار تا حد امکان. این کار به حفظ شمار عظیم بستههای شخص ثالث موجود در CRAN کمک میکند، اما توانایی بهروزرسانی R پایه با مفاهیم مدرن برنامهنویسی را محدود میسازد.
در سالهای اخیر، چندین بسته منتشر شدهاند که بر پایهی تجربهی چند دههای از نقاط قوت و ضعف طراحی اولیهی R، قابلیتهای R را گسترش میدهند و گاه جایگزین میکنند.
این بستهها مجموعهی tidyverse را تشکیل میدهند.
آنها در سال ۲۰۲۳ به اجراکنندهی آزمون Exercism افزوده شدند و در دسترس شما هستند تا در تمرینها از آنها استفاده کنید.
مسیر R ما چند سال پیش از افزودن tidyverse ساخته شده است، بنابراین ممکن است متوجه شوید که بسیاری از راهحلهای جامعه به زبان پایه پایبند میمانند.
dplyr
dplyr بیشتر دربارهی دستکاری دیتافریمهاست (که بعداً در دوره پوشش داده میشود).
آن را یا با library(dplyr) در بالای کد خود اضافه کنید، یا با library(tidyverse) برای افزودن کل مجموعه.
ممکن است پیامهای هشداری دربارهی اسمهای پوشاندهشده ببینید، اما این بهندرت مشکلی ایجاد میکند.
برای مفهوم کنونی، تابع if_else ارزش اشاره دارد.
این تابع عمدتاً مشابه ifelse در R پایه است.
library(dplyr) # warnings not shown
x <- 10
if_else(x > 8, "big", "small")
#> [1] "big"
تفاوت اصلی این است که if_else میتواند یک آرگومان چهارم اختیاری بگیرد، برای مقادیر مفقود که در R با NA نمایش داده میشوند.
xs <- c(3, NA, 10, NA, 4) # a 5-element vector
xs
#> [1] 3 NA 10 NA 4
if_else(xs > 8, "big", "small", "missing")
#> [1] "small" "missing" "big" "missing" "small"
# contrast:
ifelse(xs > 8, "big", "small")
#> [1] "small" NA "big" NA "small"
همچنین ممکن است متوجه شوید که if_else پیامهای خطای بسیار بهتری نسبت به ifelse قدیمیتر دارد.
پس از بارگذاری کتابخانهی dplyr، به تابع between() نیز دسترسی خواهید داشت.
R امکان زنجیرهسازی مقایسهها را نمیدهد، بنابراین 1 <= x <= 5 پیام خطا میدهد.
وقتی dplyr بارگذاری شده باشد، between(x, 1, 5) معادل x >= 1 & x <= 5 است و شاید خواناتر باشد.
هم حد پایین و هم حد بالا شامل میشوند.