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.
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:
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:
data.frame
. Ceci n'est pas recommandé car l'indexation est lente pour data.frames
.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.
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
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:
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)
}