Введение в R: линейная алгебра
Векторное индексирование, решатели собственных векторов, разложение по сингулярным числам и многое другое
R - очень мощный язык, разработанный специально для анализа данных, визуализации данных и машинного обучения, что делает его обязательным к изучению для любого начинающего специалиста по данным.
R особенно удобен с линейной алгеброй. Его встроенные типы данных, такие как векторы и матрицы, хорошо сочетаются со встроенными функциями, такими как решатели собственных значений и определителей, а также возможностями динамического индексирования.
В этой статье Intro to R будут рассмотрены следующие реализации темы линейной алгебры в R:
Векторы
- Назначение вектора
- Векторные операции
- Создание последовательностей
- Логические векторы
- Недостающие значения
- Индексирование векторов
Массивы и матрицы
- Массивы
- Индексирование массива
- Индексирование матриц
- Внешний продукт двух массивов
- Демонстрация: все возможные детерминанты однозначных матриц 2x2
- Обобщенное транспонирование массива
- Умножение матриц
- Собственные значения и собственные векторы
- Разложение по сингулярным значениям и детерминанты
- Аппроксимация методом наименьших квадратов и QR-разложение
- Формирование разбитых матриц
Векторы
Присвоение вектора
R работает со структурами данных, простейшим из которых является числовой вектор. Вектор - это упорядоченный набор чисел. Чтобы создать вектор x
с четырьмя элементами 1
, 2
, 3
и 4
, можно использовать функцию конкатенации c()
.
x <- c(1, 2, 3, 4)
В этом сценарии используется оператор присваивания <-
, который указывает на назначаемый объект. В большинстве случаев <-
можно переключить с помощью =
.
Функцию assign()
также можно использовать:
assign('x', c(1, 2, 3, 4))
Оператор ‹- считается ярлыком для этого.
Назначения можно делать и в обратном направлении:
c(1, 2, 3, 4) -> x
Векторные операции
Векторы также можно использовать по-разному.
Операция y <- c(x, 0, x)
назначит вектор 1, 2, 3, 4, 0, 1, 2, 3, 4
переменной y
.
Векторы можно свободно умножать и добавлять константами:
v <- 2*x + y + 1
Обратите внимание, что эта операция действительна, даже если x
и y
имеют разную длину. В этом случае R просто перерабатывает x (иногда дробно), пока не достигнет длины y. Так как y состоит из 9 чисел, а x - из 4 единиц, x будет повторяться 2,25 раза, чтобы соответствовать длине y.
Можно использовать арифметические операторы +
, -
, *
, /
и ^
. Также можно использовать log
, exp
, sin
, cos
, tan
, sqrt
и другие. max(x)
и min(x)
представляют наибольший и наименьший элементы вектора x
, а length(x)
- количество элементов в x
. sum(x)
дает общее количество элементов в x
, а prod(x)
- их произведение.
mean(x)
вычисляет среднее значение выборки, а var(x)
возвращает дисперсию выборки. sort(x)
возвращает вектор того же размера, что и x, с элементами, расположенными в порядке возрастания.
Создание последовательностей
В R есть много методов для генерации последовательностей чисел. 1:30
совпадает с c(1, 2, …, 29, 30)
. Двоеточие является наивысшим приоритетом в выражении, поэтому2*1:15
вернет c(2, 4, …, 28, 30)
вместо c(2, 3, …, 14, 15)
.
30: 1 можно использовать для создания последовательности в обратном направлении.
Функцию seq()
также можно использовать для генерации последовательностей. seq(2,10)
возвращает тот же вектор, что и 2:10
. В seq()
можно также указать длину шага, на котором нужно выполнить: seq(1,2,by=0.5)
возвращает c(1, 1.5, 2)
.
Похожая функция - rep()
, которая копирует объект различными способами. Например, rep(x, times=5)
вернет пять копий x
от начала до конца.
Логические векторы
Логические значения в R - ИСТИНА, ЛОЖЬ и НЕТ. Логические векторы задаются условиями. val <- x > 13
задает val
как вектор той же длины, что и x
, со значениями TRUE
, где условие выполняется, и FALSE
, где условие не выполняется.
Логические операторы в r - это <
, <=
, >
, >=
, ==
и !=
, что означает меньше, меньше или равно, больше, больше или равно, равенство и неравенство.
Недостающие значения
Функция is.na(x)
возвращает логический вектор того же размера, что и x
, с TRUE
, если соответствующий элемент для x
равен NA
.
x == NA
отличается от is.na(x)
, поскольку NA
- это не значение, а маркер недоступного количества.
Второй тип «пропущенного значения» - это значение, полученное с помощью числовых вычислений, например 0/0
. В этом случае значения NaN
(не число) обрабатываются как значения NA
; то есть is.na(x)
вернет TRUE
для значений NA
и NaN
. is.nan(x)
можно использовать только для идентификации NaN
значений.
Индексирование векторов
Первый вид индексации - через логический вектор. y <- x[!is.na(x)]
устанавливает y
в значения x
, которые не равны NA
или NaN
.
(x+1)[(!is.na(x)) & x>0] -> z
устанавливает z
в значения x+1
, которые не равны Na
или NaN
и больше 0.
Второй метод - с вектором положительных целых величин. В этом случае значения должны быть в наборе {1, 2, …, length(x)}
. Соответствующие элементы вектора выбираются и объединяются в указанном порядке для формирования результата. Важно помнить, что в отличие от других языков, первый индекс в R равен 1, а не 0.
x[1:10]
возвращает первые 10 элементов x
, при условии, что length(x)
не меньше 10. c(‘x’, ‘y’)[rep(c(1,2,2,1), times=4)]
создает вектор символов длиной 16, где ‘x’, ‘y’, ‘y’, ‘x’
повторяется четыре раза.
Вектор отрицательных целых чисел указывает значения, которые должны быть исключены, а не включены. y <- x[-(1:5)]
устанавливает y
для всех, кроме первых пяти значений x
.
Наконец, вектор символьных строк может использоваться, когда объект имеет атрибут names для идентификации его компонентов. С фруктом <- c(1, 2, 3, 4)
можно установить имена каждого индекса векторного фрукта с помощью names(fruit) <- c(‘mango’, ‘apple’, ‘banana’, ‘orange’)
. Затем можно вызвать элементы по имени с помощью lunch <- fruit[c(‘apple’, ‘orange’)]
.
Преимущество этого состоит в том, что буквенно-цифровые имена иногда легче запомнить, чем индексы.
Обратите внимание, что индексированное выражение также может появляться на принимающей стороне присваивания, в котором присваивание выполняется только для этих элементов вектора. Например, x[is.na(x)] <- 0
заменяет все значения NA
и NaN
в векторе x
на значение 0
.
Другой пример: y[y<0] <- -y[y<0]
имеет тот же эффект, что и y <- abs(y)
. Код просто заменяет все значения, меньшие 0, отрицательными значениями этого значения.
Массивы и матрицы
Массивы
Массив - это набор записей данных с индексами, не обязательно числовых.
Вектор размерности - это вектор неотрицательных целых чисел. Если длина k, тогда массив k -мерный. Размеры индексируются от единицы до значений, указанных в векторе размерностей.
R может использовать вектор как массив в качестве атрибута dim
attribute. Если бы z
был вектором из 1500 элементов, присвоение dim(z) <- c(100, 5, 3)
означало бы, что z
теперь обрабатывается как массив 100 на 5 на 3.
Индексирование массива
На отдельные элементы массива можно ссылаться, указав имя массива, за которым следуют нижние индексы в квадратных скобках, разделенные столбцами.
В векторе 3 на 4 на 6 a
первое значение может быть вызвано через a[1, 1, 1]
, а последнее значение - через a[3, 4, 6]
.
a[,,]
представляет весь массив; следовательно, a[1,1,]
занимает первую строку первого двумерного поперечного сечения в a
.
Индексирующие матрицы
Следующий код создает массив 4 на 5: x <- array(1:20, dim = c(4,5))
.
Массивы задаются вектором значений и размерами матрицы. Значения вычисляются сначала сверху вниз, затем слева направо.
array(1:4, dim = c(2,2))
вернется
1 3 2 4
и не
1 2 3 4
Отрицательные индексы не допускаются в индексных матрицах. NA
и нулевые значения разрешены.
Внешний продукт двух массивов
Важной операцией с массивами является внешний продукт. Если a
и b
являются двумя числовыми массивами, их внешний продукт представляет собой массив, вектор размерности которого получается объединением двух векторов размерности и вектор данных которого достигается путем формирования всех возможных произведений элементов вектора данных a
с элементами b
. Внешний продукт вычисляется с помощью оператора %o%
:
ab <- a %o% b
Другой способ добиться этого -
ab <- outer(a, b, ‘*’)
Фактически, любую функцию можно применить к двум массивам с помощью функции external (). Предположим, мы определяем функцию f <- function(x, y) cos(y)/(1+x²)
. Функцию можно применить к двум векторам x
и y
через z <- outer(x, y, f)
.
Демонстрация: все возможные детерминанты однозначных матриц 2x2
Рассмотрим определители матриц 2 на 2 [a, b; c, d], где каждая запись представляет собой неотрицательное целое число от 0 до 9. Проблема состоит в том, чтобы найти определители всех возможных матриц в этой форме и представить частоту, с которой встречается значение, с помощью графика с высокой плотностью.
Перефразируя, найдите распределение вероятностей определителя, если каждая цифра выбирается независимо и равномерно случайным образом.
Один из умных способов сделать это - дважды использовать внешнюю функцию (0.
d <- outer(0:9,0:9) fr <- table(outer(d, d, ‘-’)) plot(fr, xlab = ‘Determinant’, ylab = ‘Frequency’)
Первая строка присваивает этой матрице d:
Во второй строке снова используется функция outer () для вычисления всех возможных определителей, а в последней строке это строится.
Обобщенное транспонирование массива
Функцию aperm(a, perm)
можно использовать для перестановки массива a. Аргумент perm должен быть перестановкой целых чисел {1,…, k}, где k - количество индексов в a. Результатом функции является массив того же размера, что и, но со старым измерением, заданным perm[j]
, становится новым j-th
измерением.
Легко представить себе это как обобщение транспонирования для матриц. Если A
- матрица, то B
- это просто транспонирование A
:
B <- aperm(A, c(2, 1))
В этих особых случаях функция t()
выполняет транспонирование.
Умножение матриц
Оператор% *% используется для умножения матриц. Если A
и B
являются квадратными матрицами одинакового размера, A*B
является поэлементным произведением двух матриц. A %*% B
- это точечный продукт (матричный продукт).
Если x - вектор, то x %*% A %*% x
- квадратичная форма.
crossprod()
выполняет кросс-продукты; таким образом, crossprod(X, y)
то же самое, что и операция t(X) %*% y
, но более эффективна.
diag(v)
, где v
- вектор, дает диагональную матрицу с элементами вектора в качестве диагональных элементов. diag(M)
, где m
- матрица, дает вектор основных диагональных элементов M
(такое же соглашение, как в Matlab). diag(k)
, где k
- одно числовое значение, возвращает матрицу идентичности k
на k
.
Линейные уравнения и обращение
Решение линейных уравнений - это обратное умножение матриц. Когда
b <- A %*% x
с заданными только A
и b
вектор x
является решением системы линейных уравнений. Это можно быстро решить в R с помощью
solve(A, b)
Собственные значения и собственные векторы
Функция eigen(Sm)
вычисляет собственные значения и собственные векторы симметричной матрицы Sm. Результатом является список, в котором первый элемент назван значениями, а второй - векторами. ev <- eigen(Sm)
назначает этот список ev
.
ev$val
- это вектор собственных значений Sm
и ev$vec
матрица соответствующих собственных векторов.
Для больших матриц лучше избегать вычисления собственных векторов, если они не нужны, используя выражение
evals <- eigen(Sm, only.values = TRUE)$values
Разложение по сингулярным значениям и детерминанты
Функция svd(m)
принимает произвольный аргумент матрицы, m
, и вычисляет разложение по сингулярным значениям m
. Он состоит из матрицы ортонормированных столбцов U
с тем же пространством столбцов, что и m
, второй матрицы ортонормированных столбцов V
, пространство столбцов которых является пространством строк m
, и диагональной матрицы положительных элементов D
, таких что
m = U %*% D %*% t(V)
det(m)
можно использовать для вычисления определителя квадратной матрицы m
.
Подгонка методом наименьших квадратов и QR-разложение
Функция lsfit()
возвращает список, содержащий результаты процедуры аппроксимации методом наименьших квадратов. Задание вроде
ans <- lsfit(X, y)
дает результаты аппроксимации методом наименьших квадратов, где y - вектор наблюдений, а X - матрица плана.
ls.diag()
можно использовать для регрессионной диагностики.
Схожая функция - qr ().
b <- qr.coef(Xplus,y) fit <- qr.fitted(Xplus,y) res <- qr.resid(Xplus,y)
Они вычисляют ортогональную проекцию y
на диапазон X
в fit
, проекцию на ортогональное дополнение в res
и вектор коэффициентов для проекции в b
.
Создание разделов Matrices
Матрицы могут быть построены из других векторов и матриц с помощью функций cbind()
и rbind()
.
cbind()
формирует матрицы путем привязки матриц по горизонтали (по столбцам), а rbind()
связывает матрицы по вертикали (по строкам).
В присваивании X <- cbind(arg_1, arg_2, arg_3, …)
аргументы cbind()
должны быть либо векторами любой длины, либо столбцами с одинаковым размером столбца (одинаковым количеством строк).
rbind()
выполняет соответствующую операцию для строк.
Спасибо за прочтение!
Я надеюсь, что это Введение в R дало вам представление о мощных возможностях R в линейной алгебре.