Сначала загружаем пакет для строительства красивых графиков:

library(ggplot2)

Весёлый калькулятор

R можно использовать как весёлый калькулятор:

5 + 9
## [1] 14

Что-нибудь более интересное:

a <- factorial(4)
b <- 2^3
a + b
## [1] 32

Признайся, шалунишка, ты всегда мечтал поделить на ноль?

a <- 1 / 0
a
## [1] Inf

Что можно делать с бесконечностью?

1 / (a - 9)
## [1] 0

Возьмём арктангенс!

atan(Inf)
## [1] 1.570796

Ба! Да это же \(\pi/2\):

pi / 2
## [1] 1.570796

Но с неопределенностью ничего не поделаешь:

0 / 0
## [1] NaN

NaN расшифровывается как «Not a Number». NaN отличается от NA («Not Available», пропущенные данные); точнее, всякое NaN — NA, но не всякое NA — NaN. Проверять, является ли что-либо NA или NaN, можно так:

is.na(0 / 0)
## [1] TRUE
a <- NA
is.na(a)
## [1] TRUE
is.nan(a)
## [1] FALSE

Простые операции с векторами

Вектор из чисел по порядку:

a <- 3:10
a
## [1]  3  4  5  6  7  8  9 10

Вектор из одинаковых чисел:

b <- rep(777, times = 5)
b
## [1] 777 777 777 777 777

Вектор из конкретных чисел:

vect <- c(5, -4, 1)

Что можно делать с вектором?

sum(vect)
## [1] 2

Хотите среднее арифметическое?

mean(vect)
## [1] 0.6666667

Генерация случайных величин

Хочу 300 случайных натуральных чисел от 1 до 5 с повторами! И побыстрее!

h <- sample(1:5, 300, rep = TRUE)

Краткая информация о векторе \(h\), начало вектора \(h\) и конец вектора \(h\):

str(h)
##  int [1:300] 2 4 2 5 2 5 1 3 4 3 ...
head(h)
## [1] 2 4 2 5 2 5
tail(h)
## [1] 3 4 3 2 5 4

Команды head() и tail() позволяют отобразить не только шесть первых значений (по умолчанию), но и заданное их число:

head(h, n = 2)
## [1] 2 4

Или без последних значений:

head(h, n = -298)
## [1] 2 4

Хочу сгенирировать выборку из 100 значений случайной величины \(X\) с вероятностями:

\(X\) -2 3 7
\(P()\) 0.1 0.2 0.7

Зададим вектор вектор возможных значений и вектор вероятностей:

x.val <- c(-2, 3, 7)
x.pr <- c(0.1, 0.2, 0.7)

Получаем выборку из 100 значений:

s <- sample(x.val, 100, rep = TRUE, x.pr)
str(s)
##  num [1:100] 7 3 7 7 7 7 3 7 7 7 ...

Два простеньких графика

Простенькую гистограмму можно построить, например, с помощью функции qplot() из пакета ggplot2:

qplot(factor(s), xlab = "Значение", ylab = "Количество", main = "Гистограмма")

Ту же гистограммку можно построить с помощью функции ggplot() из того же пакета, предварительно преобразовав s в необходимый для ggplot() формат data frame:

s_df <- data.frame(s)
ggplot(s_df) + geom_bar(aes(factor(s))) + labs(x = "Значение", y = "Количество", title = "Гистограмма")

И еще простенький график:

x <- rnorm(500) # 500 нормальных величин со средним 0 и дисперсией 1
y <- rnorm(500) # 500 нормальных величин со средним 0 и дисперсией 1
qplot(x, y, main = "Точечки")

Или:

xy_df <- data.frame(x = x, y = y)
ggplot(xy_df) + geom_point(aes(x, y)) + labs(title = "Точечки")

В зависимости от формата данных часто бывает удобно использовать и qplot(), и ggplot().

Отбор значений

Выберем из вектора \(s\) значения больше \(0\):

b <- s[s > 0]
b
##  [1] 7 3 7 7 7 7 3 7 7 7 7 7 7 7 7 7 7 3 7 7 3 7 3 7 7 3 7 7 7 7 7 3 7 7 3
## [36] 7 7 7 7 7 3 7 7 7 7 7 3 7 7 3 7 7 7 7 7 7 7 7 3 7 3 7 3 7 7 7 7 3 7 3
## [71] 7 3 3 7 3 7 7 3 7 7 3 7 3 7 7 7 7 7 7
str(b)
##  num [1:89] 7 3 7 7 7 7 3 7 7 7 ...

Можно выбрать конкретные \(s\), например с 6-го по 20-ое:

s[6:20]
##  [1]  7  3  7  7  7 -2  7  7 -2  7  7  7  7  7  3

Хочу 5-ое, 7-ое и 13-ое!

s[c(5, 7, 13)]
## [1] 7 3 7

Можно узнать, сколько значений равно 3:

sum(s == 3)
## [1] 22

Еще полезная штучка — количество элементов в векторе:

length(b)
## [1] 89

Операции, похожие на те, что проделали с векторами, можно делать и с другими типами данных, например, с матрицами (matrix), таблицами (table) и др. Покажем на примере наборов данных (data frame).

Будем использовать набор данных diamonds из пакета ggplot2. Множество других встроены во многие пакеты, а также в сам R, и список с кратким описанием последних можно вызвать командой library(help = "datasets").

Наборы данных состоят из строк (rows) и столбцов (columns); в каждой строке хорошо построенного набора — характеристики одного объекта, а по столбцам — значения одной характеристики у разных объектов. Так, например, в diamonds объектами являются бриллианты, а их характеристиками — цена, вес, цвет и т. д. Это можно увидеть с помощью всё той же команды str():

str(diamonds)
## Classes 'tbl_df', 'tbl' and 'data.frame':    53940 obs. of  10 variables:
##  $ carat  : num  0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
##  $ cut    : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3 ...
##  $ color  : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 2 2 2 6 7 7 6 5 2 5 ...
##  $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 2 3 5 4 2 6 7 3 4 5 ...
##  $ depth  : num  61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
##  $ table  : num  55 61 65 58 58 57 57 55 61 61 ...
##  $ price  : int  326 326 327 334 335 336 336 337 337 338 ...
##  $ x      : num  3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
##  $ y      : num  3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
##  $ z      : num  2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...

Отобразим наблюдения с 5-го по 7-е:

diamonds[c(5:7), ]
##   carat       cut color clarity depth table price    x    y    z
## 5  0.31      Good     J     SI2  63.3    58   335 4.34 4.35 2.75
## 6  0.24 Very Good     J    VVS2  62.8    57   336 3.94 3.96 2.48
## 7  0.24 Very Good     I    VVS1  62.3    57   336 3.95 3.98 2.47

Первые 4 значения параметров цены (price) и веса (carat):

head(diamonds[, c("price", "carat")], n = 4)
##   price carat
## 1   326  0.23
## 2   326  0.21
## 3   327  0.23
## 4   334  0.29

Можно отобразить и все названия характеристик:

colnames(diamonds)
##  [1] "carat"   "cut"     "color"   "clarity" "depth"   "table"   "price"  
##  [8] "x"       "y"       "z"

Найдём, сколько камней имеют чистоту не меньшую, чем VS2 (характеристика clarity — упорядоченный фактор).

nrow(diamonds[diamonds$clarity >= "VS2", ])
## [1] 30940

Сравнение чисел — штука тонкая

Правда ли, что 0.4 + 0.1 равно 0.5?

0.4 + 0.1 == 0.5
## [1] TRUE

А правда ли, что 0.4 - 0.1 равно 0.3?

0.4 - 0.1 == 0.3
## [1] FALSE

Хм, что-то Марь Иванна в школе другое говорила…

Почему так случилось? Компьютер хранит числа в памяти в двоичной системе счисления. В двоичной системе обычное число 0.1 будет записываться в виде бесконечной периодической дроби. Следовательно, без дополнительных ухищрений храниться в памяти абсолютно точно оно не может. Поэтому де-факто компьютер хранит в памяти округленную версию от 0.4, 0.1 и 0.3. В данном случае при вычитании ошибки округления не компенсируют друг друга.