Как я могу автоматически создать список структур с помощью R? - PullRequest
4 голосов
/ 21 сентября 2011

Допустим, что RES - это список с емкостью 1000 структур, которые функция kmeans генерирует как выходные данные.

Как мне объявить RES?

После объявления RES я хочу сделать что-то вроде этого:

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

Спасибо.Руи

Ответы [ 3 ]

4 голосов
/ 21 сентября 2011

Если вы используете идиому R apply, ваш код будет проще, и вам не нужно заранее объявлять переменную:

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"
2 голосов
/ 22 сентября 2011

Я повторю, что 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, чем атомные векторы.

1 голос
/ 21 сентября 2011

Способ создания списка, к сожалению, отличается от обычного способа создания числового вектора.

# 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 не нравится вызываться с набором данных радужной оболочки, как это прямо ...)

Но с другой стороны, lapply сделает это тоже и более прямым способом, как показал @Andrie.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...