تمتلك 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() (هل كل القيم صحيحة؟) أو any() (هل قيمة واحدة على الأقل صحيحة؟).
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 في عام 2023، وهي متاحة لك لاستخدامها في التمارين.
مسار 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 يمكنها أن تأخذ وسيطًا رابعًا اختياريًا، للقيم المفقودة التي تمثّلها NA في R.
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، وربما يكون أوضح قراءة.
كلا الحدّين الأدنى والأعلى شاملان.