2010-04-01 13 views
15

Je suis en train d'écrire d'une boucle à une trame de données dans R, par exemple une boucle comme celui-ci>écrit à une trame de données à partir d'une boucle for en R

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

et d'écrire chaque ligne de 3 valeurs à un bloc de données avec trois colonnes, de sorte que chaque itération prend une nouvelle ligne. J'ai essayé d'utiliser la matrice, avec ncol = 3 et rempli par des lignes, mais seulement obtenir le dernier élément de la boucle.

Merci.

Répondre

22

Vous pouvez utiliser rbind:

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

Notez qu'il s'agit probablement de la solution la moins efficace proposée. Pour de très petits ensembles de données, cela n'aura pas d'importance, mais vous ne devriez pas utiliser rbind ou cbind dans une boucle si vous voulez être efficace. – Dason

4

Pour boucle ont des effets secondaires, donc de la manière habituelle de le faire est de créer un vide avant dataframe la boucle, puis y ajouter à chaque itération. Vous pouvez l'instancier à la bonne taille et ensuite assigner vos valeurs à la i-ème ligne à chaque itération, ou bien l'ajouter et réaffecter le tout en utilisant rbind().

La première approche aura de meilleures performances pour les grands ensembles de données.

+0

Merci pour ces deux réponses, d'attribuer des valeurs à la ligne ith voulez-vous dire quelque chose comme ça, (cela ne fonctionne pas réellement). De même, est-ce que cela fonctionnerait avec un dataframe avec un nombre inconnu de lignes? rm (d) d <- data.frame (nrow = 20, ncol = 3) pour (i dans 1:20) { d [i,] <- c (i + i, i * i, i/1)} – CCID

+0

Pourquoi avez-vous dit "nombre inconnu de lignes" lorsque votre exemple a i dans 1:20? Si le nombre de lignes est inconnu, vous devrez utiliser quelque chose comme rbind, comme le suggère une autre réponse. –

6

Si toutes vos valeurs ont le même type et que vous connaissez le nombre de lignes, vous pouvez utiliser une matrice de la manière suivante (ce sera très rapide):

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

Si vous avez besoin d'une trame de données , vous pouvez utiliser rbind (comme une autre réponse suggère), ou fonctions du package plyr comme ceci:

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

une autre façon serait

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 

Si vous ne spécifiez pas simplify = FALSE, vous devez transposer le résultat en utilisant t. Cela peut être fastidieux pour les grandes structures.

Cette solution est particulièrement pratique si vous avez un jeu de données sur le grand côté et/ou si vous devez répéter cela plusieurs fois.

Je propose quelques minutages de solutions dans ce "thread".

> 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

'spply' semble avoir obtenu plus rapidement (sur ma machine au moins) lors de l'écriture comme spply (** 1: 2e4 **, FUN = fonction (i) ** c (2 * i, i^2, i/1) **, simplifier = FAUX) –