How can I create a list of structures automatically with R?
Lets say that开发者_开发技巧 RES is a list with capacity for 1000 structs that function kmeans generates as output.
How do I declare RES?
After having RES declared I want to do something like this:
for (i in 1:1000) {
RES[i] = kmeans(iris,i)
}
Thank you. Rui
If you use the R apply idiom, your code will be simpler and you don't have to declare your variable in advance:
RES <- lapply(1:3, function(i)kmeans(dist(iris[, -5]),i))
The results:
> str(RES)
List of 3
$ :List of 7
..$ cluster : Named int [1:150] 1 1 1 1 1 1 1 1 1 1 ...
.. ..- attr(*, "names")= chr [1:150] "1" "2" "3" "4" ...
..$ centers : num [1, 1:150] 2.89 2.93 3.04 2.96 2.93 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : chr "1"
.. .. ..$ : chr [1:150] "1" "2" "3" "4" ...
..$ totss : num 55479
..$ withinss : num 55479
..$ tot.withinss: num 55479
..$ betweenss : num 4.15e-10
..$ size : int 150
..- attr(*, "class")= chr "kmeans"
$ :List of 7
..$ cluster : Named int [1:150] 1 1 1 1 1 1 1 1 1 1 ...
.. ..- attr(*, "names")= chr [1:150] "1" "2" "3" "4" ...
..$ centers : num [1:2, 1:150] 0.531 4.104 0.647 4.109 0.633 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : chr [1:2] "1" "2"
.. .. ..$ : chr [1:150] "1" "2" "3" "4" ...
..$ totss : num 55479
..$ withinss : num [1:2] 863 9743
..$ tot.withinss: num 10606
..$ betweenss : num 44873
..$ size : int [1:2] 51 99
..- attr(*, "class")= chr "kmeans"
$ :List of 7
..$ cluster : Named int [1:150] 2 2 2 2 2 2 2 2 2 2 ...
.. ..- attr(*, "names")= chr [1:150] "1" "2" "3" "4" ...
..$ centers : num [1:3, 1:150] 3.464 0.5 5.095 3.438 0.622 ...
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : chr [1:3] "1" "2" "3"
.. .. ..$ : chr [1:150] "1" "2" "3" "4" ...
..$ totss : num 55479
..$ withinss : num [1:3] 2593 495 1745
..$ tot.withinss: num 4833
..$ betweenss : num 50646
..$ size : int [1:3] 62 50 38
..- attr(*, "class")= chr "kmeans"
I'll second that lapply
is the right answer in this case.
But there are many scenarios where a loop is necessary, and it's a good question.
R lists don't need to be declared as empty ahead of time, so the easiest way to do this would to just 'declare' RES
as an empty list:
RES <- list()
for (i in 1:1000) {
RES[i] = kmeans(iris,i)
}
R will just extend the list for each iteration.
Incidentally, this works even for non-sequential indexing:
newList <- list()
newList[5] <- 100
yields a list with slots 1 through 4 designed as NULL and the number 100 in the fifth slot.
This is all just to say that lists are very different beasts in R than the atomic vectors.
The way to create a list is unfortunately different from the usual way of creating a numeric vector.
# The "usual" way to create a numeric vector
myNumVec <- numeric(1000) # A numeric vector with 1000 zeroes...
# ...But there is also this way
myNumVec <- vector("numeric", 1000) # A numeric vector with 1000 zeroes...
# ...and that's the only way to create lists:
# Create a list with 1000 NULLs
RES <- vector("list", 1000)
So your example would become,
RES <- vector("list", 1000)
for (i in 1:1000) {
RES[[i]] = kmeans(iris,i)
}
(Note that kmeans doesn't like to be called with the iris data set directly like that though...)
But then again, lapply
would do it too and in a more direct way as @Andrie showed.
精彩评论