Запись в кадр данных из цикла for в R

Я пытаюсь записать из цикла в кадр данных в R, например, цикл, подобный этому >

for (i in 1:20) {
print(c(i+i,i*i,i/1))}

и записать каждую строку из трех значений в кадр данных с тремя столбцами, так что каждая итерация берет новую строку. Я пробовал использовать матрицу с ncol = 3 и заполнялся строками, но получал только последний элемент из цикла.

Спасибо.

Ответы

Ответ 1

Вы можете использовать rbind:

d <- data.frame()
for (i in 1:20) {d <- rbind(d,c(i+i, i*i, i/1))}

Ответ 2

Другой способ:

do.call("rbind", sapply(1:20, FUN = function(i) c(i+i,i*i,i/1), simplify = FALSE))


     [,1] [,2] [,3]
 [1,]    2    1    1
 [2,]    4    4    2
 [3,]    6    9    3
 [4,]    8   16    4
 [5,]   10   25    5
 [6,]   12   36    6

Если вы не укажете simplify = FALSE, вам нужно транспонировать результат с помощью t. Это может быть утомительным для больших структур.

Это решение особенно удобно, если у вас есть набор данных на большой стороне и/или вам нужно повторять это много раз.

Я предлагаю некоторые тайминги решений в этой "теме".

> system.time(do.call("rbind", sapply(1:20000, FUN = function(i) c(i+i,i*i,i/1), simplify = FALSE)))
   user  system elapsed 
   0.05    0.00    0.05 

> system.time(ldply(1:20000, function(i)c(i+i, i*i, i/1)))
   user  system elapsed 
   0.14    0.00    0.14 

> system.time({d <- matrix(nrow=20000, ncol=3) 
+ for (i in 1:20000) { d[i,] <- c(i+i, i*i, i/1)}})
   user  system elapsed 
   0.10    0.00    0.09 

> system.time(ldply(1:20000, function(i)c(i+i, i*i, i/1)))
   user  system elapsed 
  62.88    0.00   62.99 

Ответ 3

Если все ваши значения имеют один и тот же тип, и вы знаете количество строк, вы можете использовать матрицу следующим образом (это будет очень быстро):

d <- matrix(nrow=20, ncol=3) 
for (i in 1:20) { d[i,] <- c(i+i, i*i, i/1)}

Если вам нужен фрейм данных, вы можете использовать rbind (как предлагает другой ответ), или функции из пакета plyr следующим образом:

library(plyr)
ldply(1:20, function(i)c(i+i, i*i, i/1))

Ответ 4

В цикле есть побочные эффекты, поэтому обычный способ сделать это - создать пустой цикл данных перед циклом, а затем добавить к нему на каждой итерации. Вы можете создать экземпляр до нужного размера, а затем назначить свои значения i-й строке на каждой итерации или добавить к ней и переназначить все это с помощью команды rbind().

Первый подход будет иметь лучшую производительность для больших наборов данных.