Сохранение объектов S4 в списке списка - PullRequest
5 голосов
/ 25 марта 2019

R выдает следующее сообщение об ошибке, когда вы хотите сохранить объект S4 в список списка, а элемент еще не был определен ранее.

"invalid type/length (S4/0) in vector allocation"

Почему эторабота с простым списком, но не со списком списка?

См. Следующий код и возможные обходные пути.Тем не менее, я уверен, что есть более очевидное решение.

# Creation of an S4 object
setClass("student", slots=list(name="character", age="numeric", GPA="numeric"))
s <- new("student",name="John", age=21, GPA=3.5)

# Indexes for the list
index1 <- "A"
index2 <- "a"

# Simple list (All of this works)
l <- list()
l[[index1]] <- s
l[[index1]] <- "character"
l[[index1]] <- 999


# List of list 
l <- list()
l[[index1]][[index2]] <- s          # will give an Error!!
l[[index1]][[index2]] <- "character" # still working
l[[index1]][[index2]] <- 999         # still working


# "Workarounds"
l <- list()
l[[index1]][[index2]] <- rep(999, length(slotNames(s))) #define the element with a length equal to the number of slots in the s4 object
l[[index1]][[index2]] <- s # this works now!


l[[index1]][[index2]] <- list(s) # This works too, but that's not the same result

Любое предложение о том, почему он не работает со списком списков и как я могу решить эту проблему?Спасибо

1 Ответ

3 голосов
/ 25 марта 2019

Поэтому, когда вы делаете

l <- list()
l[[index1]][[index2]] <- s

, проблема заключается в том, что l инициализируется как список, поэтому имеет смысл установить новый именованный элемент с l[[index1]], но R не имеет понятиячто хранится в l[[index1]][[index2]].Это может быть что угодно.Это может быть функция, и функции не знают, что делать с именованной операцией индексации.Например,

l <- list()
l[[index1]] <- mean
l[[index1]][[index2]] <- "character"

Но в вашем случае, когда вы попытаетесь получить значение из списка, который еще не был инициализирован, вы получите NULL.Например,

l <- list()
l[[index1]]
# NULL

R имеет особое поведение, когда вы пытаетесь установить именованное атомное значение для объекта NULL.Обратите внимание:

# NULL[["a"]] <- "character" is basically calling....
`[[<-`(NULL, "a", "character")
#           a 
# "character" 

Обратите внимание, что здесь мы получаем именованный вектор.Не списокЭто относится и к вашим «рабочим» примерам

l <- list()
l[[index1]][[index2]] <- "character"
class(l[[index1]][[index2]])
# [1] "character"

Также обратите внимание, что это не имеет ничего общего с S4.То же самое произошло бы, если бы мы попытались установить более сложное возражение, например, функцию.

l <- list()
l[[index1]][[index2]] <- mean
# Error in l[[index1]][[index2]] <- mean : 
#   invalid type/length (closure/0) in vector allocation

В таких языках, как Perl, вы можете «волшебным образом» оживить хеши с правильным синтаксисом индексации с помощью автовивификации, но это не так в R. Если вы хотите, чтобы list() существовал в l[[index1]], вам нужно явно создать его.Это будет работать

l <- list()
l[[index1]] <- list()
l[[index1]][[index2]] <- s

Опять же, это потому, что [[ ]] немного двусмысленен в R. Это общая функция индексации, не используемая исключительно со списками.

...