Jan 30: Списки и структура объектов
Изменение элементов объектов
В задачах на изменение значения элемента векторов, списков или таблиц используется следующая логика: указывается элемент объекта, с которым надо произвести какое-то действие, и этому элементу присваивается новое значение. Например, у нас есть вектор из 10 значений в случайном порядке от 1 до 10 и мы хотим возвести в квадрат третий элемент:
## 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 ...
При просмотре структуры списка, который в качестве одного из элементов содержит другой список, точно также отображается каждый элемент списка, его тип, в том числе и типы и элементы вложенного списка. Вложенный список дополнительно выделен точками и отступом:
## 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
. Выведите на печать и проанализируйте структуру объекта.Выведите на печать статистики коэффициентов линейной модели.