Треки
/
R
R
/
Салабус
/
Фільтрування векторів
Фі

Фільтрування векторів у R

3 вправи

Про концепцію Фільтрування векторів

У концепції Vectors ми бачили, що вектор можна використати в умовному виразі й отримати логічний вектор. Його, своєю чергою, можна передати у функції на кшталт all() і any().

v <- c(4, 7, 10)
v >= 6
#> [1] FALSE  TRUE  TRUE
all(v > 6)
#> [1] FALSE    # not all elements match this condition
any(v > 6)
#> [1] TRUE     # at least one element matches

Проте цей прийом значно потужніший.

Підмножини вектора

Окремі елементи вектора можна дістати за індексом або за вектором індексів:

v <- 5:10
v
#> [1]  5  6  7  8  9 10
v[3] 
#> [1] 7
v[c(2, 4)]
#> [1] 6 8

Інший спосіб: відфільтрувати початковий вектор логічним вектором і отримати підмножину елементів, яким відповідає значення TRUE:

v <- 1:3
bools <- c(FALSE, TRUE, TRUE)
v[bools]
#> [1] 2 3

Звідси лише крок до того, щоб створювати вектор булевих значень (англ. Boolean) умовним виразом:

bools <- v >= 2
bools
#> [1] FALSE  TRUE  TRUE

v[bools]
#> [1] 2 3

# simpler form
v[v >= 2]
#> [1] 2 3

Ці умовні вирази можуть бути як завгодно складними й охоплювати кілька векторів або функцій:

v <- 1:10
w <- 10:1

# pairwise comparison
v > w
#> [1] FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE

# shorter form
v[v > w]
#> [1]  6  7  8  9 10

Назва

Ми назвали цю концепцію «Фільтрування векторів», сподіваючись, що так вона буде зрозуміла якнайширшому колу програмістів.

У спільноті R, мабуть, поширеніший термін «Subsetting».

Повторне використання

Для простоти в усіх прикладах вище порівнювалися вектори однакової довжини. А що буде, якщо довжини не збігаються?

Відповідь така: ця поведінка дуже корисна, якщо використовувати її свідомо, але збиває з пантелику, якщо вона неочікувана.

Приклад:

v <- 1:6
cond <- c(TRUE, FALSE)
v[cond]
#> [1] 1 3 5

Що тут сталося? Ми проіндексували вектор довжини 6 вектором булевих значень довжини 2, а в результаті отримали вектор довжини 3.

Якщо вектор «закороткий» для виразу, у якому його використано, R повторює його, доки не досягне потрібної довжини. Це називають «повторним використанням». Так наш вектор c(TRUE, FALSE) перетворився на c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE), і v[cond] повернув ті значення v, яким відповідає TRUE, тобто в цьому випадку непарні числа.

А що відбувається в наступному прикладі?

v <- 1:3
0.5 * v
#> [1] 0.5 1.0 1.5
2 + v
#> [1] 3 4 5

Спершу це схоже на множення на скаляр і (трохи дивне) додавання скаляра, але скалярів у R немає.

Натомість числа повторюються, щоб утворити вектор тієї ж довжини, що й v, а тоді арифметична операція виконується поелементно з c(0.5, 0.5, 0.5) або c(2, 2, 2).

Caution

Повторне використання дуже, дуже корисне, але варто переконатися, що ми справді цього хочемо.

Невелика розбіжність у довжинах векторів (наприклад, 99 і 100) може спричинити заплутані помилки.

Деякі автори радять вдаватися до повторного використання лише тоді, коли один із векторів має довжину 1.

Пошук індексів

Функція which() приймає аргумент із булевими значеннями і повертає вектор індексів, для яких значення дорівнює TRUE.

v
#> [1] 2 7 9

v[v > 5]  # returns values
#> [1]  7  9

which(v > 5) # returns indices
#> [1] 2 3

Перевірка, чи є елемент у векторі

Попередні розділи були про пошук елементів, що відповідають певному критерію.

Якщо нам потрібно лише дізнатися, чи містить вектор певний елемент, використовують оператор %in%.

3 %in% 1:5
#> [1] TRUE
7 %in% 1:5
#> [1] FALSE

Функціонально це рівнозначно наведеному нижче коду, але набагато зручніше:

length(v[v == 3]) > 0
#> [1] TRUE

Є також оператор %notin%, який дає логічне not від %in%.

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

Вивчити концепцію Фільтрування векторів

Практика заблокована

Розблокуйте ще 2 вправи, щоб практикувати концепцію Фільтрування векторів