【问题标题】:How can I create a list of structures automatically with R?如何使用 R 自动创建结构列表?
【发布时间】:2011-09-21 16:31:27
【问题描述】:

假设 RES 是一个可容纳 1000 个结构的列表,函数 kmeans 作为输出生成。

如何申报 RES?

在声明 RES 之后,我想做这样的事情:

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

谢谢。 瑞

【问题讨论】:

    标签: list r structure


    【解决方案1】:

    如果你使用 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"
    

    【讨论】:

    • 很好!:) 但是,我尝试了 RES
    • 这是因为您尝试在iris 上进行聚类,而不是距离矩阵。阅读?kmeans?dist 的帮助。
    • 谢谢安德烈。这是因为kmeans。现在您的解决方案正在运行!我从 sapply 学到了一些重要的东西!
    【解决方案2】:

    我认为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 中是非常不同的野兽。

    【讨论】:

      【解决方案3】:

      不幸的是,创建列表的方式与创建数字向量的通常方式不同。

      # 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 函数输出的类型是什么。我猜它类似于“c”中的结构。我怎样才能扭转这个局面?谢谢
      • @Rui kmeans 的输出是kmeans 类的对象,本质上和列表一样。所以@Tommy 的代码可以工作(除了 kmeans 期望距离矩阵作为输入,而不是 data.frame)。
      • @Andrie,我从来没有使用带有距离矩阵的 kmeans 作为输入。我一直使用data.frame。 sapply / lapply 解决方案非常优雅。谢谢
      • @Tommy,它不起作用。 RES[2] = kmeans(iris[, -5], 2) : 要替换的项目数不是替换长度的倍数 我需要这个解决方案的原因。是因为我将使用通过多个​​内核并行化的 foreach 库。
      • @Rui - 哎呀,应该是双括号赋值(RES[[i]])。我更新了代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-07
      • 1970-01-01
      • 2021-09-22
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2019-01-27
      相关资源
      最近更新 更多