How to create a list of structures automatically using R?

Suppose RES is a list with a capacity of 1000 structures that the kmeans function generates as output.

How to declare RES?

After declaring RES, I want to do something like this:

for (i in 1:1000) { RES[i] = kmeans(iris,i) } 

Thanks. Rui

+4
source share
3 answers

If you use the R apply idiom, your code will be simpler, and you do not need to declare your variable in advance:

 RES <- lapply(1:3, function(i)kmeans(dist(iris[, -5]),i)) 

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" 
+4
source

Secondly, lapply is the correct answer in this case. But there are many scenarios where a loop is needed, and this is a good question.

Lists of R need not be declared empty ahead of time, so the easiest way to do this is to simply “declare” RES as an empty list:

 RES <- list() for (i in 1:1000) { RES[i] = kmeans(iris,i) } 

R just extends the list for each iteration.

By the way, this works even for unclassified indexing:

 newList <- list() newList[5] <- 100 

displays a list with slots 1 through 4, created as NULL, and the number 100 in the fifth slot.

That’s all we can say that lists are very different animals in R than atomic vectors.

+2
source

Unfortunately, the way to create a list is different from the usual way to create a numerical 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 the only way to create lists: # Create a list with 1000 NULLs RES <- vector("list", 1000) 

So your example will become

 RES <- vector("list", 1000) for (i in 1:1000) { RES[[i]] = kmeans(iris,i) } 

(Note that kmeans do not like to call with an aperture dataset like this, though ...)

But then again, lapply would do it in a more direct way too, as @Andrie showed.

+1
source

All Articles