R is giving the following message error when you want to save an S4 object into a list of list and the element was not already defined previously.
"invalid type/length (S4/0) in vector allocation"
Why is it working with a simple list, but not with a list of list?
See the following code and the potential workarounds. However, I am pretty sure there is a more obvious solution.
# 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
Any suggestion on why it does not work with a list of list and how I can solve this problem? Thanks
So when you do
l <- list()
l[[index1]][[index2]] <- s
the problem is that that l
is initialized to be a list so it makes sense to set a new named element with l[[index1]]
, but R has no idea what's stored at l[[index1]][[index2]]
. It could be anything. It could be a function and functions don't know what to do with a named indexing operation. For example
l <- list()
l[[index1]] <- mean
l[[index1]][[index2]] <- "character"
But in your case, when you try to grab a value form a list that hasn't been initialized yet, you'll get NULL
. For example
l <- list()
l[[index1]]
# NULL
R happens to have special behavior when you try set a named atomic value on a NULL object. Observe
# NULL[["a"]] <- "character" is basically calling....
`[[<-`(NULL, "a", "character")
# a
# "character"
Note that we are getting a named vector here. Not a list. This is true for your "working" examples as well
l <- list()
l[[index1]][[index2]] <- "character"
class(l[[index1]][[index2]])
# [1] "character"
Also note that this doesn't have anything to do with S4 specifically. The same would happen if we tried to set a more complex objected like a function as well
l <- list()
l[[index1]][[index2]] <- mean
# Error in l[[index1]][[index2]] <- mean :
# invalid type/length (closure/0) in vector allocation
In languages like Perl you can "magically" bring hashes to life with the correct indexing syntax via autovivification, but that's not true in R. If you want a list()
to exist at l[[index1]]
you will need to explicitly create it. This will work
l <- list()
l[[index1]] <- list()
l[[index1]][[index2]] <- s
Again this is because [[ ]]
is a bit ambiguous in R. It's a generic indexing function not used exclusively with lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With