R Language
Списки
Поиск…
Краткое введение в списки
В общем, большинство объектов, с которыми вы могли бы взаимодействовать как пользователь, были бы вектором; например, числовой вектор, логический вектор. Эти объекты могут принимать только один тип переменной (числовой вектор может содержать только цифры внутри него).
Список мог бы хранить в нем любую переменную типа, превращая ее в общий объект, который может хранить любые типы переменных, которые нам понадобятся.
Пример инициализации списка
exampleList1 <- list('a', 'b')
exampleList2 <- list(1, 2)
exampleList3 <- list('a', 1, 2)
Чтобы понять данные, которые были определены в списке, мы можем использовать функцию str.
str(exampleList1)
str(exampleList2)
str(exampleList3)
Подмножество списков различает извлечение фрагмента списка, т. Е. Получение списка, содержащего подмножество элементов в исходном списке, и извлечение одного элемента. Использование [
оператора, обычно используемого для векторов, создает новый список.
# Returns List
exampleList3[1]
exampleList3[1:2]
Для получения одного элемента используйте [[
вместо этого.
# Returns Character
exampleList3[[1]]
Список записей может быть назван:
exampleList4 <- list(
num = 1:3,
numeric = 0.5,
char = c('a', 'b')
)
Записи в именованных списках могут быть доступны по имени, а не по индексу.
exampleList4[['char']]
Альтернативно, оператор $
можно использовать для доступа к именованным элементам.
exampleList4$num
Это имеет то преимущество, что оно быстрее печатается и может быть легче читать, но важно знать о потенциальной ловушке. Оператор $
использует частичное сопоставление для идентификации элементов списка соответствия и может привести к неожиданным результатам.
exampleList5 <- exampleList4[2:3]
exampleList4$num
# c(1, 2, 3)
exampleList5$num
# 0.5
exampleList5[['num']]
# NULL
Списки могут быть особенно полезными, поскольку они могут хранить объекты различной длины и разных классов.
## Numeric vector
exampleVector1 <- c(12, 13, 14)
## Character vector
exampleVector2 <- c("a", "b", "c", "d", "e", "f")
## Matrix
exampleMatrix1 <- matrix(rnorm(4), ncol = 2, nrow = 2)
## List
exampleList3 <- list('a', 1, 2)
exampleList6 <- list(
num = exampleVector1,
char = exampleVector2,
mat = exampleMatrix1,
list = exampleList3
)
exampleList6
#$num
#[1] 12 13 14
#
#$char
#[1] "a" "b" "c" "d" "e" "f"
#
#$mat
# [,1] [,2]
#[1,] 0.5013050 -1.88801542
#[2,] 0.4295266 0.09751379
#
#$list
#$list[[1]]
#[1] "a"
#
#$list[[2]]
#[1] 1
#
#$list[[3]]
#[1] 2
Введение в списки
Списки позволяют пользователям хранить несколько элементов (например, векторов и матриц) под одним объектом. Вы можете использовать функцию list
для создания списка:
l1 <- list(c(1, 2, 3), c("a", "b", "c"))
l1
## [[1]]
## [1] 1 2 3
##
## [[2]]
## [1] "a" "b" "c"
Обратите внимание, что векторы, составляющие вышеуказанный список, представляют собой разные классы. Списки позволяют пользователям группировать элементы разных классов. Каждый элемент в списке также может иметь имя. Имена списков доступны с помощью функции names
и назначаются тем же образом, имена строк и столбцов назначаются в матрице.
names(l1)
## NULL
names(l1) <- c("vector1", "vector2")
l1
## $vector1
## [1] 1 2 3
##
## $vector2
## [1] "a" "b" "c"
При создании объекта списка часто проще и безопаснее объявлять имена списков.
l2 <- list(vec = c(1, 3, 5, 7, 9),
mat = matrix(data = c(1, 2, 3), nrow = 3))
l2
## $vec
## [1] 1 3 5 7 9
##
## $mat
## [,1]
## [1,] 1
## [2,] 2
## [3,] 3
names(l2)
## [1] "vec" "mat"
Выше списка есть два элемента, называемые «vec» и «mat», вектор и матрица, нереально.
Причины использования списков
Для среднего пользователя R структура списка может оказаться одной из более сложных структур данных для управления. Нет никаких гарантий того, что все элементы внутри него одного типа; Не существует гарантированной структуры того, насколько сложным / не сложным будет список (элементом в списке может быть список)
Однако, одна из основных причин, когда использовать списки, чтобы использовать его для передачи параметров между функциями.
# Function example which returns a single element numeric vector
exampleFunction1 <- function(num1, num2){
result <- num1 + num2
return(result)
}
# Using example function 1
exampleFunction1(1, 2)
# Function example which returns a simple numeric vector
exampleFunction2 <- function(num1, num2, multiplier){
tempResult1 <- num1 + num2
tempResult2 <- tempResult1 * multiplier
result <- c(tempResult1, tempResult2)
return(result)
}
# Using example function 2
exampleFunction2(1, 2, 4)
В приведенном выше примере возвращаемые результаты - это просто простые числовые векторы. Нет никаких проблем для прохождения таких простых векторов.
На этом этапе важно отметить, что в общем случае функции R возвращают только один результат за один раз (вы можете использовать, если условия возвращают разные результаты). Однако, если вы намереваетесь создать функцию, которая принимает набор параметров и возвращает несколько типов результатов, таких как числовой вектор (значение настроек) и кадр данных (из расчета), вам нужно будет сбросить все эти результаты в список прежде чем возвращать его.
# We will be using mtcars dataset here
# Function which returns a result that is supposed to contain multiple type of results
# This can be solved by putting the results into a list
exampleFunction3 <- function(dataframe, removeColumn, sumColumn){
resultDataFrame <- dataframe[, -removeColumn]
resultSum <- sum(dataframe[, sumColumn])
resultList <- list(resultDataFrame, resultSum)
return(resultList)
}
# Using example function 3
exampleResult <- exampleFunction3(mtcars, 2, 4)
exampleResult[[1]]
exampleResult[[2]]
Преобразование списка в вектор, сохраняя пустые элементы списка
Когда вы хотите преобразовать список в вектор или объект data.frame, пустые элементы обычно удаляются.
Это может быть проблематично, что список создается из требуемой длины, создаются с пустым значением (например, создается список с n элементами, которые должны быть добавлены в матрицу mxn, data.frame или data.table). Однако можно без потерь преобразовать список в вектор, сохраняя пустые элементы:
res <- list(character(0), c("Luzhuang", "Laisu", "Peihui"), character(0),
c("Anjiangping", "Xinzhai", "Yongfeng"), character(0), character(0),
c("Puji", "Gaotun", "Banjingcun"), character(0), character(0),
character(0))
res
[[1]] character(0) [[2]] [1] "Luzhuang" "Laisu" "Peihui" [[3]] character(0) [[4]] [1] "Anjiangping" "Xinzhai" "Yongfeng" [[5]] character(0) [[6]] character(0) [[7]] [1] "Puji" "Gaotun" "Banjingcun" [[8]] character(0) [[9]] character(0) [[10]] character(0)
res <- sapply(res, function(s) if (length(s) == 0) NA_character_ else paste(s, collapse = " "))
res
[1] NA "Luzhuang Laisu Peihui" NA "Anjiangping Xinzhai Yongfeng" NA [6] NA "Puji Gaotun Banjingcun" NA NA NA
Сериализация: использование списков для передачи информации
Существуют случаи, когда необходимо объединить данные разных типов. Например, в Azure ML необходимо передавать информацию из модуля сценариев R в другой исключительно через данные. Предположим, что у нас есть dataframe и число:
> df
name height team fun_index title age desc Y
1 Andrea 195 Lazio 97 6 33 eccellente 1
2 Paja 165 Fiorentina 87 6 31 deciso 1
3 Roro 190 Lazio 65 6 28 strano 0
4 Gioele 70 Lazio 100 0 2 simpatico 1
5 Cacio 170 Juventus 81 3 33 duro 0
6 Edola 171 Lazio 72 5 32 svampito 1
7 Salami 175 Inter 75 3 30 doppiopasso 1
8 Braugo 180 Inter 79 5 32 gjn 0
9 Benna 158 Juventus 80 6 28 esaurito 0
10 Riggio 182 Lazio 92 5 31 certezza 1
11 Giordano 185 Roma 79 5 29 buono 1
> number <- "42"
Мы можем получить доступ к этой информации:
> paste(df$name[4],"is a",df3$team[4], "supporter." )
[1] "Gioele is a Lazio supporter."
> paste("The answer to THE question is", number )
[1] "The answer to THE question is 42"
Чтобы поместить различные типы данных в фрейм данных, мы должны использовать объект списка и сериализацию. В частности, мы должны помещать данные в общий список, а затем помещать список в определенный фреймворк данных:
l <- list(df,number)
dataframe_container <- data.frame(out2 = as.integer(serialize(l, connection=NULL)))
После того, как мы сохранили информацию в фрейме данных, нам нужно десериализовать его, чтобы использовать его:
#----- unserialize ----------------------------------------+
unser_obj <- unserialize(as.raw(dataframe_container$out2))
#----- taking back the elements----------------------------+
df_mod <- unser_obj[1][[1]]
number_mod <- unser_obj[2][[1]]
Затем мы можем проверить правильность передачи данных:
> paste(df_mod$name[4],"is a",df_mod$team[4], "supporter." )
[1] "Gioele is a Lazio supporter."
> paste("The answer to THE question is", number_mod )
[1] "The answer to THE question is 42"