web-dev-qa-db-fra.com

Remplir une trame de données dans R dans une boucle

J'essaie de renseigner un cadre de données dans une boucle for en R. Les noms des colonnes sont générés de manière dynamique dans la boucle et la valeur de certaines variables de la boucle est utilisée comme valeurs lors du remplissage du cadre de données. Par exemple, le nom de la colonne actuelle pourrait être un nom de variable sous forme de chaîne dans la boucle, et la colonne pourrait prendre la valeur de l'itérateur actuel comme valeur dans le cadre de données.

J'ai essayé de créer un cadre de données vide en dehors de la boucle, comme ceci

d = data.frame()

Mais je ne peux vraiment rien faire avec, au moment où je tente de le peupler, je tombe dans une erreur

 d[1] = c(1,2)
Error in `[<-.data.frame`(`*tmp*`, 1, value = c(1, 2)) : 
  replacement has 2 rows, data has 0

Quel peut être un bon moyen de réaliser ce que je cherche à faire. S'il vous plaît laissez-moi savoir si je n'étais pas clair.

24
ganesh reddy

Vous pouvez le faire comme ceci:

 iterations = 10
 variables = 2

 output <- matrix(ncol=variables, nrow=iterations)

 for(i in 1:iterations){
  output[i,] <- runif(2)

 }

 output

puis le transformer en un data.frame

 output <- data.frame(output)
 class(output)

qu'est-ce que cela fait:

  1. créer une matrice avec des lignes et des colonnes en fonction de la croissance attendue
  2. insérer 2 nombres aléatoires dans la matrice
  3. convertissez ceci en un cadre de données après la boucle est terminée.
31
Seb

Il est souvent préférable d'éviter les boucles et d'utiliser des fonctions vectorisées. Si cela n’est pas possible, il existe deux approches:

  1. Préallouez votre data.frame. Ceci n'est pas recommandé car l'indexation est lente pour data.frames.
  2. Utilisez une autre structure de données dans la boucle et transformez-la ensuite en data.frame. Une list est très utile ici.

Exemple pour illustrer l'approche générale:

mylist <- list() #create an empty list

for (i in 1:5) {
  vec <- numeric(5) #preallocate a numeric vector
  for (j in 1:5) { #fill the vector
    vec[j] <- i^j 
  }
  mylist[[i]] <- vec #put all vectors in the list
}
df <- do.call("rbind",mylist) #combine all vectors into a matrix

Dans cet exemple, il n'est pas nécessaire d'utiliser list, vous pouvez préallouer une matrix. Cependant, si vous ne savez pas combien d'itérations seront nécessaires à votre boucle, vous devez utiliser un list.

Enfin, voici une alternative vectorisée à la boucle d'exemple:

outer(1:5,1:5,function(i,j) i^j)

Comme vous le voyez, c'est plus simple et plus efficace.

39
Roland

cela fonctionne aussi.

df = NULL
for (k in 1:10)
    {
       x = 1
       y = 2
       z = 3
       df = rbind(df, data.frame(x,y,z))
     }

la sortie ressemblera à ceci

df #enter

x y z #col names
1 2 3
3
Notable1

J'ai eu un cas dans lequel j'avais besoin d'utiliser un cadre de données dans une fonction de boucle for. Dans ce cas, c’était «efficace», mais gardez à l’esprit que la base de données était petite et que les itérations dans la boucle étaient très simples. Mais peut-être que le code pourrait être utile pour quelqu'un avec des conditions similaires. 

La boucle for avait pour but d’utiliser la fonction raster extract sur cinq emplacements (5 Tokio, New York, Sao Paulo, Seul et Mexico) et chaque emplacement avait sa grille de trame respective. J'avais une base de données de points spatiaux avec plus de 1000 observations réparties dans les 5 emplacements différents et j'avais besoin d'extraire des informations de 10 grilles de trame différentes (deux grilles par emplacement). De plus, pour l'analyse suivante, j'avais besoin non seulement des valeurs de raster, mais également de l'identifiant unique pour chaque observation.

Après avoir préparé les données spatiales, qui comprenaient les tâches suivantes:

  1. Importer un fichier de formes avec la fonction readOGR (paquetage rgdap)
  2. Importer des fichiers raster avec la fonction raster (package raster)
  3. Empiler des grilles du même emplacement dans un seul fichier, avec la fonction stack (package raster) 

Voici le code pour la boucle avec l'utilisation d'un cadre data:

1. Ajouter des rasters empilés par emplacement dans une liste

raslist <- list(LOC1,LOC2,LOC3,LOC4,LOC5)

2. Créez une image vide, ce sera le fichier de sortie

TB <- data.frame(VAR1=double(),VAR2=double(),ID=character())

3. Configuration de la fonction de boucle

L1 <- seq(1,5,1) # the location ID is a numeric variable with values from 1 to 5 

for (i in 1:length(L1)) {
  dat=subset(points,LOCATION==i) # select corresponding points for location [i] 
  t=data.frame(extract(raslist[[i]],dat),dat$ID) # run extract function with points & raster stack for location [i]
  names(t)=c("VAR1","VAR2","ID") 
  TB=rbind(TB,t)
}
0
scs76