J'essaie d'apprendre R et je ne vois pas comment l'ajouter à une liste.
Si c'était Python je le ferais. . .
#Python
vector = []
values = ['a','b','c','d','e','f','g']
for i in range(0,len(values)):
vector.append(values[i])
Comment faites-vous cela en R?
#R Programming
> vector = c()
> values = c('a','b','c','d','e','f','g')
> for (i in 1:length(values))
+ #append value[i] to empty vector
Voici plusieurs façons de le faire. Tous sont découragés. L'ajout à un objet dans une boucle for entraîne la copie de l'objet entier à chaque itération, ce qui oblige de nombreuses personnes à dire "R est lent" ou "Les boucles R doivent être évitées".
# one way
for (i in 1:length(values))
vector[i] <- values[i]
# another way
for (i in 1:length(values))
vector <- c(vector, values[i])
# yet another way?!?
for (v in values)
vector <- c(vector, v)
# ... more ways
help("append")
aurait répondu à votre question et vous aurait évité le temps nécessaire pour l'écrire (mais vous aurait amené à développer de mauvaises habitudes). ;-)
Notez que vector <- c()
n'est pas un vecteur vide; c'est NULL
. Si vous voulez un vecteur de caractère vide, utilisez vector <- character()
.
Notez aussi que BrodieG indiqué dans les commentaires: si vous devez absolument utiliser une boucle for, alors au moins allouer le vecteur entier avant la boucle. Ce sera beaucoup plus rapide que l'ajout de plus grands vecteurs.
set.seed(21)
values <- sample(letters, 1e4, TRUE)
vector <- character(0)
# slow
system.time( for (i in 1:length(values)) vector[i] <- values[i] )
# user system elapsed
# 0.340 0.000 0.343
vector <- character(length(values))
# fast(er)
system.time( for (i in 1:length(values)) vector[i] <- values[i] )
# user system elapsed
# 0.024 0.000 0.023
FWIW: analogue à append () de python:
b <- 1
b <- c(b, 2)
Vous avez quelques options:
c(vector, values)
append(vector, values)
vector[(length(vector) + 1):(length(vector) + length(values))] <- values
Le premier est l'approche standard. La seconde vous donne la possibilité d’ajouter un endroit autre que la fin. Le dernier est un peu déformé mais présente l’avantage de modifier vector
(bien que vous puissiez aussi facilement faire vector <- c(vector, values)
.
Notez que dans R, vous n’avez pas besoin de parcourir les vecteurs. Vous pouvez simplement les opérer en entier.
En outre, il s’agit là de choses assez basiques, vous devriez donc consulter certaines des les références.
Quelques options supplémentaires basées sur les commentaires de l'OP:
for(i in values) vector <- c(vector, i)
Juste pour compléter, ajouter des valeurs à un vecteur dans une boucle for n'est pas vraiment la philosophie de R. R fonctionne mieux en agissant sur les vecteurs dans leur ensemble, comme l'a souligné @BrodieG. Voyez si votre code ne peut pas être réécrit comme:
ouput <- sapply(values, function(v) return(2*v))
La sortie sera un vecteur de valeurs de retour. Vous pouvez également utiliser lapply
si valeurs est une liste au lieu d'un vecteur.
Parfois, nous devons utiliser des boucles, par exemple, lorsque nous ne savons pas combien d'itérations nous avons besoin d'obtenir le résultat. Prenez les boucles while par exemple. Vous trouverez ci-dessous des méthodes à éviter absolument:
a=numeric(0)
b=1
system.time(
{
while(b<=1e5){
b=b+1
a<-c(a,pi)
}
}
)
# user system elapsed
# 13.2 0.0 13.2
a=numeric(0)
b=1
system.time(
{
while(b<=1e5){
b=b+1
a<-append(a,pi)
}
}
)
# user system elapsed
# 11.06 5.72 16.84
Celles-ci sont très inefficaces car R copie le vecteur à chaque fois qu’il s’ajoute.
Le moyen le plus efficace d’ajouter est d’utiliser index. Notez que cette fois, je le laisse itérer 1 à 7 fois, mais c'est toujours beaucoup plus rapide que c
.
a=numeric(0)
system.time(
{
while(length(a)<1e7){
a[length(a)+1]=pi
}
}
)
# user system elapsed
# 5.71 0.39 6.12
Ceci est acceptable Et nous pouvons accélérer un peu en remplaçant [
par [[
.
a=numeric(0)
system.time(
{
while(length(a)<1e7){
a[[length(a)+1]]=pi
}
}
)
# user system elapsed
# 5.29 0.38 5.69
Peut-être avez-vous déjà remarqué que length
peut prendre beaucoup de temps. Si nous remplaçons length
par un compteur:
a=numeric(0)
b=1
system.time(
{
while(b<=1e7){
a[[b]]=pi
b=b+1
}
}
)
# user system elapsed
# 3.35 0.41 3.76
Comme d'autres utilisateurs l'ont mentionné, pré-allouer le vecteur est très utile. Mais c’est un compromis entre vitesse et utilisation de la mémoire si vous ne savez pas combien de boucles vous devez obtenir pour obtenir le résultat.
a=rep(NaN,2*1e7)
b=1
system.time(
{
while(b<=1e7){
a[[b]]=pi
b=b+1
}
a=a[!is.na(a)]
}
)
# user system elapsed
# 1.57 0.06 1.63
Une méthode intermédiaire consiste à ajouter progressivement des blocs de résultats.
a=numeric(0)
b=0
step_count=0
step=1e6
system.time(
{
repeat{
a_step=rep(NaN,step)
for(i in seq_len(step)){
b=b+1
a_step[[i]]=pi
if(b>=1e7){
a_step=a_step[1:i]
break
}
}
a[(step_count*step+1):b]=a_step
if(b>=1e7) break
step_count=step_count+1
}
}
)
#user system elapsed
#1.71 0.17 1.89
> vec <- c(letters[1:3]) # vec <- c("a","b","c") ; or just empty vector: vec <- c()
> values<- c(1,2,3)
> for (i in 1:length(values)){
print(paste("length of vec", length(vec)));
vec[length(vec)+1] <- values[i] #Appends value at the end of vector
}
[1] "length of vec 3"
[1] "length of vec 4"
[1] "length of vec 5"
> vec
[1] "a" "b" "c" "1" "2" "3"
En R, vous pouvez essayer de cette façon:
X = NULL
X
# NULL
values = letters[1:10]
values
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
X = append(X,values)
X
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
X = append(X,letters[23:26])
X
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "w" "x" "y" "z"