---
title: "Основы программирования в R"
subtitle: "Векторы в R: часть 1"
author: "Алла Тамбовцева, НИУ ВШЭ"
output:
  pdf_document:
    latex_engine: xelatex
    toc: true
mainfont: CMU Serif
header-includes:
- \usepackage[russian]{babel}
- \usepackage{hyperref}
- \hypersetup{colorlinks = true, urlcolor = blue, linkcolor=magenta}
---

## Числовые векторы

Вектор в R – список некоторых объектов. Для тех, кто знаком с Python: вектор можно сравнить с массивом (*array*) или списком (*list*), состоящим из элементов одного типа. Технически, элементы вектора могут иметь разный тип, но тогда вектор будет уже не тот — увидим это позже.

Создадим вектор `v`, состоящий из целых чисел. Для объединения элементов в вектор используется базовая функция `c()`:

```{r}
v <- c(1, 0, 0, 2)
v
```

Какие характеристики вектора мы можем получить? Из самых простых — тип его элементов и длина. Определим тип:

```{r}
class(v)
```

А теперь длину — число элементов вектора:

```{r}
length(v)
```

Перейдём к более интересным характеристикам числового вектора. Посчитаем сумму его элементов:

```{r}
sum(v)
```

Произведение элементов (`prod()` от *product*):

```{r}
prod(v)
```

Среднее арифметическое:

```{r}
mean(v)
```

И медиану:

```{r}
median(v)
```

Кроме того, если рассмотреть числовой вектор как выборку, мы сможем продолжить список описательных статистик: выборочные квантили, дисперсия, стандартное отклонение, минимум, максимум... Посмотрим, как всё это вычислять в R. 

Для вычисления квантилей в R есть функция с очень логичным названием `quantile()`. На вход эта функция принимает числовой вектор и уровень квантиля. Создадим вектор побольше и найдём для него квантиль уровня 0.2:

```{r}
w <- c(9, 4, 5, 6, 1, 0, -1, 2, 3)
quantile(w, 0.2)
```

Итак, 20% значений `w` не превышают значения 0.6. 

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

```{r}
quantile(w, c(0.25, 0.5, 0.75))
```

Теперь вычислим показатели разброса значений — дисперсию и стандартное отклонение:

```{r}
# variance
var(w)
```

```{r}
# standard deviation
sd(w)
```

И вернёмся к показателям попроще — найдём минимум и максимум:

```{r}
min(w)
max(w)
```

Если продолжать разговор об описании выборки, то можно вспомнить о ранжировании наблюдений. R умеет вычислять ранги, для этого существует функция `rank()`:

```{r}
rank(w)
```

Если в векторе есть повторяющиеся значения, для них R считает усреднённые ранги. Посмотрим на это на примере вектора `v`:

```{r}
rank(v)
```

Где ранжирование элементов — там и сортировка. Для сортировки в R используется функция `sort()`. 

```{r}
sort(w)
```

Если нас интересует сортировка по убыванию, пригодится аргумент `decreasing`:

```{r}
sort(w, decreasing = TRUE)
```

Теперь давайте рассмотрим операции, которые можно выполнять сразу с несколькими числовыми векторами. Создадим два вектора:

```{r}
x <- c(1, 0, 0, 2)
y <- c(0, 1, 1, 2)
```

С числовыми векторами в R мы можем осуществлять те же операции, что и с векторами в математике. Но результаты не всегда совпадают. Например, обычное умножение векторов с помощью знака `*` не соответствует ни скалярному, ни векторному произведению векторов. Это происходит потому, что арифметические операции с векторами выполняются поэлементно.

Сложим два вектора:

```{r}
x + y
```

А теперь перемножим:

```{r}
x * y
```

Если вас интересует скалярное произведение векторов, как в математике, то оператор для умножения уже будет другим (полезный факт, тот же оператор можно использовать для умножения матриц):

```{r}
# dot product
x %*% y
```

Для объединения векторов, любых, не только числовых, используется уже знакомая нам функция `c()` (аналог методов `.append()` и `.extend()` в Python):

```{r}
result <- c(x, y)
result
```


## Текстовые векторы

Векторы могут быть текстовыми, то есть содержать элементы типа `character`:

```{r}
name <- c("Ann", "Mike", "Ben")
name
```

О том, как работать с текстом в R, мы ещё будем говорить отдельно, а пока посмотрим на что-то совсем простое — перевод всех букв в строчные или заглавные:

```{r}
tolower(name)
toupper(name)
```

## Типы элементов и приведение типов

Так как вектор умеет хранить данные только одного типа, в случае, если в векторе встречаются два типа, один из них неизбежно «вытеснит» другой. Так, текстовый тип (`character`) «вытеснит» числовой (`numeric`):

```{r}
mixed <- c(2, "one", 3)
class(mixed)
```

При работе с данными нужно всегда внимательно относиться к типу объектов. Например, если у нас есть результаты опроса студентов, и мы видим, что пять респондентов не указали свой возраст, не стоит кодировать эти пропущенные значения словом «нет». Лучше оставить значения пропущенными или закодировать их заведомо невозможным значением (например, 1000), чтобы потом ответы этиих респондентов спокойно отфильтровать. Социологи так обычно и поступают: ответы на вопросы кодируются небольшими числами (например, от 1 до 6, от 1 до 10), а пропущенные значения кодируются числами 98 или 99.

Как и у обычных переменных, у векторов можно изменять тип, то есть тип всех элементов вектора. Например, можем преобразовать текстовый вектор в числовой с помощью функции `as.numeric()`:

```{r}
text <- c("2", "3", "5")
as.numeric(text)
```

Или в целочисленный:

```{r}
as.integer(text)
```

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

```{r}
as.numeric(c("2.3", "5", "6"))
```

Грустная новость: если бы в `"2.3"` разделителем являлась запятая, ничего бы не получилось – R в качестве разделителя разрядов признает только точку:

```{r}
as.numeric(c("2,3", "5", "6"))
```

Что делать? В таком случае нужно сначала заменить запятую на точку с помощью функции `gsub()`, а уже потом преобразовывать:

```{r}
as.numeric(gsub(",", ".", c("2,3", "5", "6")))
```

## Работа с элементами вектора

Для начала создадим текстовый вектор:

```{r}
people <- c("Mary", "Peter", "John")
people
```

Для того, чтобы выбрать элементы вектора по их индексу (положению в векторе), нужно учитывать, что в R нумерация начинается с 1, а не с 0, как в Python и многих языках программирования.

```{r}
people[1]
```

Если мы выберем элемент с индексом 0, R вернёт нам пустой элемент:

```{r}
people[0]
```

Для выбора нескольких элементов, стоящих подряд, можно использовать срезы:

```{r}
people[1:2]
```

Если нужно выбрать элементы, которые следуют в векторе не подряд, индексы интересующих нас элементов нужно оформить в виде вектора:

```{r}
people[c(1, 3)]
```

При желании выбор элементов подряд и не подряд можно объединить:

```{r}
people[c(1:2, 2:3)]
```

Обратите внимание: в отличие от Python, в R правый конец среза включается. Например, код `names[1:2]` вернёт первые два элемента, а не только элемент с индексом 1.

А теперь мы будем отбирать элементы вектора по их значению. Для этого необходимо указывать интересующие критерии выбора (условия) в квадратных скобках. Создадим новый вектор `v`:

```{r}
v <- c(1, 8, 9, 2, 3, 0, -1)
```

Выберем элементы `v`, которые больше 3:

```{r}
v[v > 3]
```

Как работает этот код? Давайте отдельно запустим строку с выражением, которое стоит в квадратных скобках:

```{r}
v > 3
```

R вернул нам вектор из `TRUE` и `FALSE`, где `TRUE` стоит на месте элементов, для которых условие выполняется. Соответственно, при запуске кода `v[v > 3]` R отбирает только те элементы, на месте которых в `v > 3` стоят `TRUE`.

Усложним задачу. Будем выбирать только чётные элементы вектора `v`. Для этого нам понадобится оператор для определения остатка от деления: `%%`. Чётные элементы – те, которые делятся на 2 без остатка. Значит, остаток от деления их на 2 должен быть равен нулю:

```{r}
v[v%%2 == 0]
```

Условия можно сочетать:

```{r}
v[v > 3 & v %% 2 == 0]
v[v > 3 | v %% 2 == 0]
```

Иногда нам нужно не найти элемент вектора по его номеру или по определённым критериям, а выполнить обратную задачу: вернуть индекс элемента (его порядковый номер в векторе). Это можно сделать с помощью функции `which()`:

```{r}
which(v > 8)
which(v > 3)
which(v > 10)
```

Обратите внимание: в случае, если сразу несколько элементов удовлетворяет некоторому условию, функция `which()` возвращает индексы всех, а не только первого подходящего элемента.