Jan 30: Списки и структура объектов

Запись занятия

Запись занятия 30 января:

Все записи организованы в плейлист


Изменение элементов объектов

В задачах на изменение значения элемента векторов, списков или таблиц используется следующая логика: указывается элемент объекта, с которым надо произвести какое-то действие, и этому элементу присваивается новое значение. Например, у нас есть вектор из 10 значений в случайном порядке от 1 до 10 и мы хотим возвести в квадрат третий элемент:

# задаём зерно для псевдослучайной генерации
set.seed(1234)

# создаём вектор
x <- sample(10)
str(x)
##  int [1:10] 10 6 5 4 1 8 2 7 9 3
# возводим в квадрат третий элемент:
x[3] <- x[3] ^ 2
str(x)
##  num [1:10] 10 6 25 4 1 8 2 7 9 3

Создание новых элементов или удаление уже существующих производятся аналогично: указывается индекс элемента (или его название, если применимо), и присваивается какое-то значение. Для создания элемента – любой объект, если он не нарушает уже существующую структуру (например, в таблице на пять строк нельзя создать колонку с шестью значениями). Если в векторе создавать значение иного типа, чем был, то все значения будут преобразованы к более общему по правилам преобразования.

# меняем 9 элемент вектора на 'x', текстовый
x[9] <- 'x'
str(x)
##  chr [1:10] "10" "6" "25" "4" "1" "8" "2" "7" "x" "3"

Для удаления элемента вектора можно просто сделать переприсвоение этому объекту тех же значений, за исключением того, которое требуется удалить:

# удалим 3 значение вектора x
x <- x[-3]
str(x)
##  chr [1:9] "10" "6" "4" "1" "8" "2" "7" "x" "3"

Списки

Список элементов разных типов: векторов, таблиц, атомарных типов, других листов, функций и так далее. Длина и тип объекта в списке значения не имеет.

Создание списков

Для создания списка используется команда list(), где в аргументах через запятую перечисляются все элементы, которые необходимо включить в лист. Например:

x <- seq(from = 13, to = 0, by = -3)
y <- rep(x = 'c', times = 3)
z <- TRUE

my_list <- list(x, y, z)
str(my_list)
## List of 3
##  $ : num [1:5] 13 10 7 4 1
##  $ : chr [1:3] "c" "c" "c"
##  $ : logi TRUE

Именованные списки

Помимо простого объединения объектов в списки и последующим вызовом элементов по номеру в списке, можно создавать именованные списки, в которых каждые элементы будут иметь заданное название. Например,

x <- seq(from = 13, to = 0, by = -3)
y <- rep(x = 'c', times = 3)
z <- TRUE

my_list <- list(seq_example = x, 
                rep_example = y, 
                atomic_example = z)
print(my_list)
## $seq_example
## [1] 13 10  7  4  1
## 
## $rep_example
## [1] "c" "c" "c"
## 
## $atomic_example
## [1] TRUE

Выбор элемента списка

Выбор элементов списка также использует выбор по номеру элемента. Следует учитывать, что для списков несколько различается поведение операторов [ и [[. Так, оператор [ позволяет выделить элемент списка в виде отдельного списка:

# создадим список
my_list <- list(seq_example = seq(from = 13, to = 0, by = -3), 
                rep_example = rep(x = 'c', times = 3), 
                atomic_example = TRUE)
str(my_list)
## List of 3
##  $ seq_example   : num [1:5] 13 10 7 4 1
##  $ rep_example   : chr [1:3] "c" "c" "c"
##  $ atomic_example: logi TRUE
# выберем первый элемент списка
first_element <- my_list[1]
str(first_element)
## List of 1
##  $ seq_example: num [1:5] 13 10 7 4 1

Оператор [[ позволяет вызвать значения вызываемых элементов списка. Так, my_list[[1]] вызовет не первый элемент в виде списка, а значения первого элемента в виде вектора (как они и были заданы):

# выберем значения первого элемента списка
first_element_values <- my_list[[1]]
str(first_element_values)
##  num [1:5] 13 10 7 4 1

Также для именованных списков можно использовать выделение по имени элемента. Для указания элемента списка используется оператор $ и конструкция вида list_name$element_name. Например:

# смотрим на список
my_list
## $seq_example
## [1] 13 10  7  4  1
## 
## $rep_example
## [1] "c" "c" "c"
## 
## $atomic_example
## [1] TRUE
# выбираем элемент seq_example
str(my_list$seq_example)
##  num [1:5] 13 10 7 4 1

Структура объектов

Нередко при работе с разными объектами необходимо получить сводную информацию об объекте — класс объекта, иерархию элементов объекта, первые значения каждого элемента и так далее. Для этих целей используется функция str() (от structure), которая выводит каждый элемент объекта в виде вектора значений. Например, при просмотре структуры таблицы iris мы получаем класс объекта (data.frame), количество строк и столбцов, название колонок, тип элементов и первые десять значений каждой колонки:

str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

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

x <- list(e1 = 1:5,
          e2 = letters[1:5],
          e3 = list(e31 = rnorm(5), 
                    e32 = runif(5)))
str(x)
## List of 3
##  $ e1: int [1:5] 1 2 3 4 5
##  $ e2: chr [1:5] "a" "b" "c" "d" ...
##  $ e3:List of 2
##   ..$ e31: num [1:5] 0.983 -0.622 -0.732 -0.517 -1.751
##   ..$ e32: num [1:5] 0.8106 0.5257 0.9147 0.8313 0.0458

Домашнее задание

  • Создайте список l1, где первый элемент - случайные пять элементов вектора letters, а второй - пять случайных значений из вектора seq(from = 1, to = 50, by = 7)

  • Модифицируйте предыдущее задание - создайте именованный список l1, где первый элемент назван как id, а второй элемент - value. Выведите на печать структуру списка l1.

  • C помощью $ вызовите значения второго элемента списка l1. Сделайте это еще и через индекс (по номеру позиции).

  • Код ниже создает тестовый датасет и иллюстрирует работу линейной регрессии. Выполните выражения.

# создаем векторы значений для x (независимая/предиктор) и y (зависимая/таргет)
x <- rnorm(100)
y <- 5 * x + rlnorm(100, 1, 0.01)

# строим линейную регрессию
lm_fit <- lm(y ~ x)
lm_fit_summary <- summary(lm_fit)
  • Выведите на печать объект lm_fit_summary. Выведите на печать и проанализируйте структуру объекта.

  • Выведите на печать статистики коэффициентов линейной модели.