R

Часть 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.

  1. Функция some_func_variable доступна и для функции some_func, и another_func.
  2. 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-файла

Запись в 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)

Вот, что происходит при выполнении этого кода:

  1. Вычисление отдельных значений из множества.
  2. Затем функция определяет частоту каждого элемента и создаёт на основе этих данных таблицу.
  3. И в конце она находит указатель на элемент, который имеет самую высокую частоту появления и возвращает ее в качестве моды.

Среднеквадратичное отклонение

Среднеквадратичное отклонение — это отклонение от значений среднего арифметического. 

sd <- sd(A)
print(sd)

Дисперсия 

Дисперсия — это среднеквадратичное отклонение в квадрате:  

var <- var(A)
print(var)

Корреляция

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

cor <- cor(A, B)
print(cor)

Мы можем пользоваться определенным методом корреляции, например, коэффициентом ранговой корреляции Кендалла или Спирмена. По умолчанию используется коэффициент корреляции Пирсона.

Помещайте метод корреляции в аргумент метода.

Окончание материала будет в третьей части…

Части также:


Перевод статьи Farhad Malik: R — Statistical Programming Language