2010-04-01 11 views
15

Staram się pisać z pętlą do ramki danych w R, na przykład pętlę jak ten>zapisu na dataframe z pętli for w R

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

i napisać każdą linię 3 wartości do ramki danych z trzema kolumnami, aby każda iteracja przyjmowała nowy wiersz. Próbowałem użyć macierzy, z ncol = 3 i wypełnione wierszami, ale tylko ostatni element z pętli.

Dzięki.

Odpowiedz

22

Można użyć rbind:

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

Należy zauważyć, że jest to prawdopodobnie najmniej skuteczne rozwiązanie. W przypadku bardzo małych zbiorów danych nie będzie to miało większego znaczenia, ale naprawdę nie powinieneś używać pętli rbind lub cbind wewnątrz pętli, jeśli chcesz być efektywny. – Dason

4

Dla pętli mają skutki uboczne, więc zwykle to sposobem jest stworzenie pustego dataframe przed pętli, a następnie dodać do niej w każdej iteracji. Możesz utworzyć instancję do poprawnego rozmiaru, a następnie przypisać wartości do i-tego wiersza w każdej iteracji lub dodać do niego i ponownie przypisać całą rzecz za pomocą rbind().

Poprzednie podejście będzie miało lepszą wydajność w przypadku dużych zestawów danych.

+0

Dziękuję za obie te odpowiedzi, aby przypisać wartości do owego wiersza, masz na myśli coś takiego, (to tak naprawdę nie działa). Czy w ten sposób działałby z ramką danych o nieznanej liczbie wierszy? rm (d) d <- data.frame (nrow = 20, ncol = 3) dla (w 1:20) { d [i,] <- c (i + i, i * i, i/1)} – CCID

+0

Dlaczego powiedziałeś "nieznany brak wierszy", gdy twój przykład ma ja w 1:20? Jeśli istnieje nieznana liczba wierszy, musisz użyć czegoś podobnego do rbind, co sugeruje inna odpowiedź. –

6

Jeśli wszystkie wartości mają ten sam typ i wiesz liczbę wierszy, można użyć macierzy w następujący sposób (To będzie bardzo szybko):

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

Jeśli potrzebujesz ramki danych można użyć rbind (jak sugeruje inną odpowiedź) lub funkcji z pakietu plyr tak:

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

Innym sposobem byłoby

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 

Jeśli nie podasz simplify = FALSE, musisz przetransponować wynik za pomocą t. Może to być uciążliwe dla dużych konstrukcji.

To rozwiązanie jest szczególnie przydatne, jeśli masz zestaw danych po dużej stronie i/lub musisz go powtarzać wiele razy.

Oferuję pewne takty rozwiązań w tym "wątku".

> 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 
+0

'sapply' wydaje się, że przyśpieszyło (przynajmniej na moim komputerze) podczas pisania go jako sapply (** 1: 2e4 **, FUN = funkcja (i) ** c (2 * i, i^2, i/1) **, uprość = FALSE) –