web-dev-qa-db-fra.com

Ajouter une valeur au vecteur vide dans R?

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
133
O.rka

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 
176
Joshua Ulrich

FWIW: analogue à append () de python:

b <- 1
b <- c(b, 2)
54
Matt O'Brien

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)
26
BrodieG

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.

14
antoine

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
5
user2923419
> 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"
2
Surya

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"
2
Sowmya S. Manian