Треки
/
R
R
/
Салабус
/
Умовні конструкції
Ум

Умовні конструкції у R

2 вправи

Про концепцію Умовні конструкції

Оператори порівняння

У 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"
}

У цьому випадку обовʼязкові і дужки ( ) навколо булевого значення (англ. Boolean), і фігурні дужки { } навколо тіла.

Просту умовну конструкцію 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() приймає рівно три параметри:

  1. булева умова
  2. значення, якщо TRUE
  3. значення, якщо FALSE.

Вхідні дані можуть бути векторами, і тоді на виході отримаємо вектор. У цьому випадку переконаймося, що обидві гілки дають однаковий тип даних: числовий, символьний, логічний тощо. Про це йтиметься в концепції vector-functions.

Обидва результати ("big", "small" у прикладі вище) мають бути одиничними значеннями. На жаль, якщо передати сюди довший вектор, R, найімовірніше, зробить щось заплутане й несподіване і не видасть жодного попереджувального повідомлення.

Функція if_else

Історія питання

Супровідники мови R дотримуються політики якомога більше уникати змін, що ламають сумісність. Це допомагає підтримувати величезну кількість сторонніх пакетів, доступних у CRAN, але обмежує можливість оновлювати базовий R сучасними концепціями програмування.

Останніми роками вийшло кілька пакетів, які розширюють, а іноді й замінюють функціональність R, спираючись на десятиліття досвіду вивчення сильних і слабких сторін початкового дизайну R.

Ці пакети утворюють колекцію tidyverse. Їх додали до системи запуску тестів Exercism у 2023 році, і ми можемо використовувати їх у вправах.

Наш трек R зʼявився на кілька років раніше, ніж додали tidyverse, тож можна помітити, що багато рішень спільноти тримаються базового R.

Пакет 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 і, можливо, читається краще. І нижня, і верхня межі включні.

Редагувати через GitHub Посилання відкривається в новому вікні або вкладці

Вивчити концепцію Умовні конструкції