Векторы

Запись занятия

Запись занятия 16 сентября:


Векторы

Простой набор значений одного атомарного типа.

Атомарные типы данных

  • numeric (integer для целых и double как аналог numeric). Используется для числовых значений. Некоторые функций, в частности, median() на вход требуют объекты типа numeric.
  • character. Используется для строковых значений. Любой набор знаков, заключенный в кавычки, в R воспринимается как строковое значение.
  • logical. Значения TRUE/FALSE.


Создание векторов

Чаще всего векторы создаются с помощью функции c() (c от combine). Например:

x <- c(1, 3, 5)
print(x)
## [1] 1 3 5

Простую неименованную последовательность атомарного типа можно задать также другими командами, наиболее часто используемые из них:

  • seq() — создание последовательности значений в указанном интервале, с заданным шагом (seq от sequence). Например:
x <- seq(from = 10, to = 2, by = -2)
print(x)
## [1] 10  8  6  4  2

Первые два аргумента задают первое и последнее значения последовательности, а аргумент by - шаг последовательности (по умолчанию равен единице). Знак - для значения аргумента by маркирует, что последовательность убывающая.

  • : — аналог функции seq(), используется для создания последовательности целых чисел, где последующее отличается от предыдущего на 1. Так выражение 5:1 тождественно выражению seq(5, 1, -1).

  • rep() — повтор какого-либо элемента заданное число раз. В качестве элемента может выступать практически любой объект R (в зависимости от осмысленности в целом подобного выражения). Аргументы times или each задают, какое количество раз повторять весь объект или каждый элемент объекта соответственно:

x <- c('a', 'b', 'c')
rep(x, times = 2)
## [1] "a" "b" "c" "a" "b" "c"
rep(x, each = 2)
## [1] "a" "a" "b" "b" "c" "c"

Если значения аргументов задавать позиционно, то первый аргумент — это итерируемый объект, а второй аргумент — аргумент times:

rep(x, 2)
## [1] "a" "b" "c" "a" "b" "c"
  • sample() — создание последовательности случайно выбранных значений из какого-то заданного вектора значений. Первый аргумент задает выборку, из которой необходимо извлечь подвыборку, второй аргумент (size) определяет объем извлекаемой выборки. Аргумент replace определяет, выборка извлекается с возвращением элементов или нет:
sample(x = 1:5, size = 5, replace = FALSE)
## [1] 3 5 1 4 2
sample(x = 1:5, size = 5, replace = TRUE)
## [1] 4 5 4 1 2

Приведение типов

R используется достаточно простая система автоматического преобразования атомарных типов по логике от “самого строгого к самому гибкому”, то есть по цепочке logical -> integer -> numeric -> complex -> character (тип raw не включается в эту систему). Такое преобразование позволяет использовать конструкции вида sum(5 == 5), потому что логический результат сравнения (TRUE) будет преобразован в целое числовое значение (1, так как TRUE преобразовывается в 1, а FALSE - в 0), и, следовательно, можно вычислить количество верных утверждений.

Подобные процедуры крайне часто используются когда, например, надо посчитать количество определенных значений в векторе значений (или в колонке в таблице). Вообще, для избежания неожиданных результатов, рекомендуется избегать неявных преобразований и контролировать типы самостоятельно.

Примеры приведений типов, все приводится к самому общему:

# к строке
c('a', 3.6, 'b', 5.1, TRUE)
## [1] "a"    "3.6"  "b"    "5.1"  "TRUE"
# к numeric
c(TRUE, 3.6, 2)
## [1] 1.0 3.6 2.0


Выбор элемента вектора

Выбор элементов векторов указывается с помощью оператора [ по следующей схеме: x[<condition>]. Это читается как 'элементы вектора x, которые удовлетворяют условию <condition>'.

В качестве условия может быть номер элемента в последовательности (индекс), так и какое-то логическое условие. При использовании оператора [ в <condition> может быть передан вектор значений (или логическое выражение, возвращающее вектор значений).


Выбор по номеру позиции

Простой вариант выбора определенных элементов последовательности - по номеру в последовательности (по индексу, индекс начинается с 1). Например, в последовательности 4, 3, 2 на третьем месте находится значение 2. В коде выбор третьего элемента этой последовательности выглядит вот так:

x <- c(4, 3, 2)
x[3]
## [1] 2

В список номеров последовательности также можно передавать не только единичное значение, но и вектор значений номеров последовательности, который мы хотим извлечь. Например:

x <- c(4, 3, 2, 1)
x[c(2, 4)]
## [1] 3 1


Выбор по значению

Также возможен выбор элементов вектора, которые удовлетворяют условию. Например, те, которые больше 10, или все, которые равны 3, или все четные. Логика такого выделения следующая: каждый элемент последовательности сравнивается с условием, и если сравнение верное (5 == 5, TRUE), то этот элемент возвращается как подходящий под условие. Фактически метка TRUE здесь является указателем элемента, который надо вернуть, аналогично номеру позиции при выделении по номеру позиции.

Например:

# создаем вектор 8 случайных значений из массива от 1 до 10
x <- sample(1:10, 8)
x
## [1] 10  6  5  4  1  8  2  7
# сравниваем каждое значение с 5, смотрим результат сравнения
x_cond <- x > 5
x_cond
## [1]  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE
# делаем выбор по условию, с указанием вектора, удовлетворяет элемент условию или нет
x[x_cond]
## [1] 10  6  8  7
# аналогично, но без создания отдельного вектора
x[x > 5]
## [1] 10  6  8  7


Проверка на NA

В R есть несколько инструментов для работы с пропущенными или отсутствующими значениями.

  • NAnot avaliable. Ситуация, когда значение пропущено. Например, для какой-то строки в колонке таблицы нет значения.
  • NaN, Infnot a number и infinite соответственно. Появляются при некорректных с математической точки зрения операциях (например, 0/0 и `1/0’ соответственно).
  • NULL — объект и тип, используется в редких случаях, когда надо создать пустой объект (например x <- NULL, но это плохая практика, для этого есть более корректные способы). Чаще нужен, когда надо удалить колонку в табличке.

Для того, чтобы проверить, есть ли пропущенные значения в векторе, используется функция is.na(). Эта функция проверяет, есть ли значение у каждого элемента вектора (является NA или нет) и отдает вектор логических значений, где TRUE означает, что у соответствующего элемента в проверяемом векторе нет значения (он пропущен).

# делаем вектор с одним NA-значением
x <- c(1, 3, NA, 5)

# проверяем каждый элемент на то, пропущен он или нет
# видим, что для третьего элемента стоит TRUE, то есть пропущен
is.na(x)
## [1] FALSE FALSE  TRUE FALSE

Функцию is.na() можно точно также использовать для ивзлечения элементов вектора. Например, если мы хотим вернуть все не-пропущенные значения, нам надо воспользоваться оператор логического отрицания !. Этот оператор превращает TRUE в FALSE и наоборот:

# смотрим, как работает оператор !
!TRUE
## [1] FALSE
# пробуем извлечь все непропущенные значения из x
x[!is.na(x)]
## [1] 1 3 5


Домашнее задание

  • Из вектора month.name (уже есть в базовом R, не надо создавать) извлеките пятый элемент.
  • Из вектора month.name извлеките все элементы кроме пятого.
  • Из вектора month.name извлеките первый, пятый и последний элементы.
  • ** Создайте вектор vec из первых семи элементов вектора letters (уже есть в базовом R, не надо создавать), перемешанных в случайном порядке. Примените к нему функцию order(). Проинтерпретируйте результат.
  • *** Отсортируйте вектор vec с использованием order() и без использования sort()
  • Сравните каждый элемент вектора vec <- letters[1:5] с буквой c (равен или нет) и запишите в отдельный векторindices. Выведите indices на печать. Примените indices для выбора элементов вектора vec (vec[indices]). Проинтерпретируйте результат.
  • Из вектора month.name извлеките каждый третий элемент (вам поможет материал первого занятия).
  • Из вектора vec <- sample(10, 8) выберите все элементы, значения которых больше либо равны 5.
  • Из вектора vec <- sample(100, 8) выберите максимальное значение (элемент с максимальным значением).
  • *** Решите предыдущее задание с помощью функции which.max(). Прочитайте справку по функции и найдите “подводный камень”, который потенциально может привести к ошибкам. Попробуйте представить ситуацию, когда может возникнуть такая ошибка (необязательно при работе с векторами, например, при работе с таблицами).
  • Из вектора vec <- sample(100, 8) выберите максимальное и минимальное значения.