【发布时间】:2011-09-21 16:31:27
【问题描述】:
假设 RES 是一个可容纳 1000 个结构的列表,函数 kmeans 作为输出生成。
如何申报 RES?
在声明 RES 之后,我想做这样的事情:
for (i in 1:1000) {
RES[i] = kmeans(iris,i)
}
谢谢。 瑞
【问题讨论】:
假设 RES 是一个可容纳 1000 个结构的列表,函数 kmeans 作为输出生成。
如何申报 RES?
在声明 RES 之后,我想做这样的事情:
for (i in 1:1000) {
RES[i] = kmeans(iris,i)
}
谢谢。 瑞
【问题讨论】:
如果你使用 R 应用成语,你的代码会更简单,你不必提前声明你的变量:
RES <- lapply(1:3, function(i)kmeans(dist(iris[, -5]),i))
结果:
> 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"
【讨论】:
iris 上进行聚类,而不是距离矩阵。阅读?kmeans 和?dist 的帮助。
我认为lapply 在这种情况下是正确的答案。
但是有很多场景需要循环,这是一个很好的问题。
R 列表不需要提前声明为空,因此最简单的方法是将RES 声明为空列表:
RES <- list()
for (i in 1:1000) {
RES[i] = kmeans(iris,i)
}
R 只会为每次迭代扩展列表。
顺便说一句,这甚至适用于非顺序索引:
newList <- list()
newList[5] <- 100
产生一个列表,其中插槽 1 到 4 设计为 NULL,第五个插槽中的数字 100。
这只是说列表与原子向量在 R 中是非常不同的野兽。
【讨论】:
不幸的是,创建列表的方式与创建数字向量的通常方式不同。
# 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)
所以你的例子会变成,
RES <- vector("list", 1000)
for (i in 1:1000) {
RES[[i]] = kmeans(iris,i)
}
(请注意,kmeans 不喜欢像那样直接使用 iris 数据集调用...)
但话又说回来,lapply 也会这样做,而且会像 @Andrie 所展示的那样以更直接的方式。
【讨论】:
kmeans 的输出是kmeans 类的对象,本质上和列表一样。所以@Tommy 的代码可以工作(除了 kmeans 期望距离矩阵作为输入,而不是 data.frame)。
RES[[i]])。我更新了代码。