Часть 1, Часть 2
Предыдущую часть мы закончили темой векторов, а в этой — переходим к матрицам.
9. Что такое матрица?
Матрица, как структура данных, тоже часто встречается в R.
Её можно рассматривать как расширение понятия вектора. У матрицы может быть множество строчек и столбцов. Все элементы матрицы должны иметь один тип данных.
Чтобы создать матрицу, пользуйтесь конструктором matrix(), а функции nrow и ncol пригодятся вам, чтобы определить количество строк и столбцов соответственно:
x <- matrix(nrow=4, ncol=4)
Так получается матричная переменная под названием x с 4-мя строками и 4-мя столбцами. Вектор можно трансформировать в матрицу, используя для этого конструктор matrix. Результирующая матрица будет заполняться по столбцам:
vector <- c(1, 2, 3)
x <- matrix(vector)
print(x)
Так получится матрица с одним столбцом и тремя строками (по одной для каждого элемента):
[,1]
[1,] 1
[2,] 2
[3,] 3
Если нам нужно заполнить матрицу по строкам или столбцам, тогда мы можем явно передать их количество при помощи параметра byrow:
vector <- c(1, 2, 3, 4)
x <- matrix(vector, nrow=2, ncol=2, byrow=TRUE)
print(x)
Этот код создаёт матрицу с 2-мя столбцами и строчками. Заполняется матрица построчно.
[,1] [,2]
[1,] 1 2
[2,] 3 4
10. Что такое списки и факторы?
Если мы хотим создать множество, в котором будут элементы разных типов, то нам стоит сделать список.
Списки
Списки — это очень важная структура данных в R. Чтобы создать список, пользуйтесь конструктором list():
my_list <- list("hello", 1234, FALSE)
Эта строчка кода иллюстрирует то, как создаётся список из трёх элементов с разными типами данных.
Мы можем получить доступ к любому элементу при помощи указателя. Например, так:
item_one = my_list[1]
Этот код в результате напишет “hello”.
Ещё мы можем назвать каждый элемент. К примеру, так:
my_named_list <- list(“A”=1, “B”=2)
my_named_list <- list(“A”=1, “B”=2)
Выводит “A” “B”
print(my_named_list[‘A’])
Выводит 1
Факторы
Факторы — это категориальные данные. Например: “да”, “нет” или “мужской”, “женский”, или “красный”, “синий”, “зелёный” и т.д.
Тип данных “фактор” можно использовать для представления факторного множества данных:
my_factor = factor(c(TRUE, FALSE, TRUE))
print(my_factor)
Факторы также можно упорядочить (отсортировать):
my_factor = factor(c(TRUE, FALSE, TRUE), levels = c(TRUE, FALSE))
print(my_factor)
А ещё можем вывести факторы в формате таблицы:
my_factor = factor(c(TRUE, FALSE, TRUE), levels = c(TRUE, FALSE))
print(table(my_factor))
Это даст следующий результат:
TRUE FALSE
2 1
А сейчас давайте разберёмся с вопросами, связанными со статистикой.
11. Что такое датафреймы?
Многим, даже практически всем, научным проектам по работе с данными нужно на вход подавать таблицы. Датафрейм — это структура, которая нужна для представления табличных данных в R. В каждом столбце — список элементов. В разных столбцах могут быть разные типы (данных).
Чтобы создать датафрейм из 2-х столбцов и 5-ти строк, напишите следующее:
my_data_frame <- data.frame(column_1 = 1:5, column_2 = c("A", "B", "C", "D", E"))
print(my_data_frame)column_1 column_2
1 1 A
2 2 B
3 3 C
4 4 D
5 5 E
12. Различные логические операции в R
В этом разделе рассмотрим общепринятые операторы.
OR (или): первое | второе
Этот оператор проверяет, верно ли первое, или второе. Это дизъюнкция.
AND (и): первое & второе
Этот оператор проверяет, верно ли первое и второе. Это называется конъюнкция.
NOT: !input
Этот оператор возвращает true, если было введено false. И наоборот. Операцию ещё называют инверсией.
Также можем пользоваться операторами:
< меньше, чем;
<= меньше или равно;
=> больше или равно;
> больше, чем;
isTRUE(input) верно для вводимого;и другие.
13. Функции и область действия переменных в R
Иногда нам нужно, чтобы код решал не одну, а сразу комплекс задач. Эти задачи можно группировать в формате функций. А функции — это очень важные объекты в R.
В функцию можно передавать аргументы, а она может возвращать объект.
В установленном пакете R есть определенное количество встроенных функций, в том числе: length(), mean() и т.д.
Каждый раз, когда мы объявляем функцию (или переменную) и вызываем её, она ищется в текущем окружении, а также рекурсивно ищется в родительских окружениях до тех пор, пока значение не будет найдено.
У функции есть имя. Оно хранится в окружении R. В теле функции находятся её операторы.
Функция может возвращать значение и может принимать ряд аргументов (второе опционально).
Чтобы создать функцию, нам нужно написать следующее:
name_of_function <- function(argument1...argumentN) {
Body of the function
}
К примеру, мы можем создать функцию, которая берёт два целых числа и возвращает их сумму:
my_function <- function(x, y) {
z <- x + y
return(z)
}
Чтобы вызвать функцию, нам нужно передать ей аргументы:
z <- my_function(1,2)
print(z)
Так на выходе получим 3.
Ещё мы можем установить значения по умолчанию для аргумента таким образом, чтобы оно было использовано в случае, когда значение аргументу не присвоено:
my_function <- function(x, y=2) {
z <- x + y
return(z)
}
output <- my_function(1)
print(output)
Значение по умолчанию y — 2. Так что мы можем вызвать функцию без присвоения значения y.
Запомните ключевое: используйте фигурные скобки {…}.
Давайте посмотрим на сложный случай, в котором мы будем использовать логический оператор.
Предположим, что нужно создать функцию, которая принимает следующие аргументы: Mode (режим), x и y.
- Если значение Mode равно True (истинно), то складываем x и y.
- Если Mode False (ложное), то мы производим операцию вычитания между x и y.
my_function <- function(mode, x, y) {
if (mode == TRUE)
{
z <- x + y
return(z)
}
else
{
z <- x - y
return(z)
}
}
Чтобы вызвать функцию сложения x и y, можем сделать так:
output <- my_function(TRUE, 1, 5)
print(output)
Это выведет 6.
Разберём код ниже. В частности, посмотрим, где наше print(z):
my_function <- function(mode, x, y) {
if (mode == TRUE)
{
z <- x + y
return(z)
}
else
{
z <- x - y
return(z)
}
#что происходит, если мы пробуем вывести z
print(z)
}
Ключевой момент в том, что z выводится после закрытия скобок.
Будет ли переменная z доступна здесь? Это подводит нас к теме области действия в функциях.
Функция может быть объявлена внутри другой функции:
some_func <- function() {
some_func_variable <- 456
another_func <- function() {
another_func_variable <- 123
}
}
В примере выше some_func и another_func — это две функции. another_func объявляется внутри функции some_func. В результате another_func() является частной по отношению к some_func(). Следовательно она недоступна внешнему миру.
Если я выполню функцию another_func() снаружи функции some_func, как это показано ниже:
another_func()
Мы получим ошибку:
Error in another_func() : could not find function “another_func”
Ошибка в функции another_func() : невозможно найти функцию “another_func”.
С другой же стороны, мы можем выполнить another_func() внутри some_func() и она сработает именно так, как и ожидалось.
Теперь рассмотрим этот код, чтобы понять, как работает область действия в R.
- Функция some_func_variable доступна и для функции some_func, и another_func.
- another_func_variable доступна только для функции another_func.
some_func <- function() {
some_func_variable <- "DEF"
another_func <- function() {
another_func_variable <- "ABC"
print(some_func_variable)
print("Inside another func" + another_func_variable)
}
print(some_func_variable)
print("outside another func" + another_func_variable)
another_func()
}
some_func()
Выполнение этого кода приведёт к возникновению исключения в R-Studio:
> some_func()
[1] “DEF”
Error in print(“outside another func” + another_func_variable) :
object ‘another_func_variable’ not found
Это значит примерно следующее: ошибка при выводе, объект ‘another_func_variable’ не обнаружен.
Как говорится в сообщении об ошибке, another_func_variable не обнаружена. Мы можем увидеть, что было выведено DEF, а это было значение, которое присвоили переменной some_func_variable.
Если мы хотим получить доступ и присвоить значения глобальной переменной, то будем пользоваться оператором <<. Переменная ищется во фрейме родительского окружения. Если переменная не найдена, то создаётся глобальная переменная.
Чтобы добавить неизвестное количество аргументов, напечатайте следующее:
my_func <- function(a, b, ...)
{
print(c)
}my_func(a=1,b=2,c=3)
14. Циклы в R
В языке R поддерживаются также управляющие структуры. Исследователи данных могут добавить логики в код R. В этом разделе я расскажу о самых важных управляющих структурах.
Циклы for
Иногда нам бывает нужно проитерировать элементы из множества. Синтаксис будет следующим:
for (i in some_collection) {
print(i)
}
В примере выше итератор может быть списком, вектором и так далее. Сниппет выше работает так, что в результате выводятся элементы множества.
Ещё мы можем написать цикл для своего множества при помощи функции seq_along(). Она обрабатывает множество и генерирует последовательность целых чисел.
Циклы while
Иногда нам нужен цикл, который выполняется, пока условие верно. А когда условие становится ложным, мы выходим из цикла.
Мы можем пользоваться циклом while, чтобы получить необходимую функциональность.
В коде ниже мы устанавливаем значения: x = 3, а z = 0. Впоследствии мы увеличиваем значение z на 1 каждый раз, пока значение z равно или больше, чем x.
x <- 3
z <- 0
while(z < x) {
z <- z + 1
}
If Else (опционально)
If Then Else часто используется в программировании.
Если коротко, условие оценивается в управляющем блоке. Если оно правдивое, то код будет выполнен, а иначе будет выполнен следующий блок, который может быть описан при помощи Else If или Else.
if(condition is true) {
# выполняются операторы
}
Также можем ввести опциональное else:
if(condition is true) {
# выполняются операторы
}
else if (another condition is true) {
# выполняются операторы
}
else {
# выполняются операторы
}
x <- 3
y <- 0
if (x == 3) {
y <- 1
}
else if (x<3) {
y <- 2
}
else {
y <- 3
}
Repeat
Если мы хотим повторить последовательность операторов неизвестное количество раз (например, пока условие выполняется или пользователь продолжает вводить значения), тогда мы можем повторять/прерывать операторы. Команда break заканчивает итерацию.
repeat {
print("hello")
x <- random()
if (x > 0.5)
{
break; #exit the loop
}
}
Если нам нужно пропустить итерацию, то мы можем воспользоватся следующим оператором:
repeat {
print("hello")
x <- random()
if (x > 0.5)
{
next #iterate again
}
}
15. Чтение и запись внешних данных в R
R предлагает для работы ряд пакетов, которые позволяют читать и записывать внешние данные. Например, Excel-файлы и таблицы SQL. В текущем разделе я описываю способы реализации этого.
Читаем файл эксель
library(openxlsx)
path <-"C:/Users/farhadm/Documents/Blogs/R.xlsx"
res <- read.xlsx(path, 'Sheet1')
head(res)
В результате отобразятся верхние строки:
Запись в Excel-файл
columnA <- runif(100,0.1,100)
columnB <- runif(100,5,1000)
df <- data.frame(columnA, columnB)
write.xlsx(df, file = path, sheetName="NewSheet",
append=TRUE)
Создаётся новый файл Excel с таблицей под названием NewSheet:
Чтение таблицы SQL
Мы может читать данные из SQL-таблицы.
library(RODBC)
db <- odbcDriverConnect('driver={SQL
Server};server=SERVERNAME;database=DATABASENAME;trusted_connection=true')
res <- sqlQuery(db, 'SQL QUERY')
Запись в таблицу SQL
Можем записывать данные в SQL-таблицы.
sqlSave(odbcConnection, some data frame, tablename="TABLE", append=TRUE, rownames=FALSE)
16. Статистические вычисления в R
R известен как один из самых популярных языков программирования для статистической обработки данных. Встроенные статистические функции очень важно понимать. В этом разделе я расскажу о самых популярных статистических вычислениях, которые производят исследователи данных.
Заполнение недостающих значений
Одна из самых частых задач в проекте исследования данных — это заполнение пропущенных значений. Мы можем пользоваться is.na(), чтобы найти элементы, которые имеют нулевое значение (NA (Not Available — «не доступно») или NAN (Not a Number — «не число»)):
vec <- c("test", NA, "another test")
is.na(vec)
В результате выведется FALSE TRUE FALSE (ложно, истинно, ложно), указывая на второй элемент в NA.
Чтобы вы лучше разобрались, скажу, что is.na() возвращает все те элементы NA. А функция is.nan() вернёт все объекты NaN. Важно помнить, что NaN это NA, но не наоборот. NA не является NaN.
Заметка: многие статистические функции, например mean, median, и так далее, принимают аргумент na.rm — он указывает, хотим ли мы удалить (переместить) na (недостающие значения).
Некоторые вычисления далее будут производиться на следующих двух векторах:
A <- c(1,2,5,6.4,6.7,7,7,7,8,9,3,4,1.5,0,10,5.1,2.4,3.4, 4.5, 6.7)
B <- c(4,4.1,0,1.4,2,1,6.7,7,5,5,8,9,3,2,2.5,0,10,5.1,4.3,5.7)
print(length(A)) #20
print(length(B)) #20
Оба вектора A и B содержат числовые значения 20-ти элементов.
Среднее арифметическое значение
Среднее арифметическое значение вычисляется путем сложения значения в множестве и затем делением на общее количество значений:
my_mean <- mean(A)
print(my_mean)
Медиана
Медиана — среднее значение в отсортированном множестве. Если количество значений четное, то медиана будет средним значением двух значений в середине:
my_median <- median(A)
print(my_median)
Мода
Она показывает самое часто повторяющееся значение. В R нет стандартной встроенной функции для вычисления моды. Но при этом мы можем создать функцию для такого расчёта, смотрите на пример:
distinct_A <- unique(A)
matches <- match(A, distinct_A)
table_A <- tabulate(matches)
max_A <- which.max(table_A)
mode<-distinct_A[max_A]
print(mode)
Вот, что происходит при выполнении этого кода:
- Вычисление отдельных значений из множества.
- Затем функция определяет частоту каждого элемента и создаёт на основе этих данных таблицу.
- И в конце она находит указатель на элемент, который имеет самую высокую частоту появления и возвращает ее в качестве моды.
Среднеквадратичное отклонение
Среднеквадратичное отклонение — это отклонение от значений среднего арифметического.
sd <- sd(A)
print(sd)
Дисперсия
Дисперсия — это среднеквадратичное отклонение в квадрате:
var <- var(A)
print(var)
Корреляция
При помощи корреляции мы можем понять, связаны ли множества друг с другом и взаимодействуют ли они, если между ними значительная связь:
cor <- cor(A, B)
print(cor)
Мы можем пользоваться определенным методом корреляции, например, коэффициентом ранговой корреляции Кендалла или Спирмена. По умолчанию используется коэффициент корреляции Пирсона.
Помещайте метод корреляции в аргумент метода.
Окончание материала будет в третьей части…
Части также:
- Анализ текста средствами языка программирования R
- 10 Расширений VS Code Insider для веб разработки 2020
- Изучаем Python: генераторы, стримы и yield
Перевод статьи Farhad Malik: R — Statistical Programming Language