Поиск…


Краткое введение в списки

В общем, большинство объектов, с которыми вы могли бы взаимодействовать как пользователь, были бы вектором; например, числовой вектор, логический вектор. Эти объекты могут принимать только один тип переменной (числовой вектор может содержать только цифры внутри него).

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

Пример инициализации списка

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"


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow