Waarde toevoegen aan lege vector in R?

Ik probeer R te leren en ik weet niet hoe ik iets aan een lijst kan toevoegen.

Als dit Python was, zou ik . . .

#Python
vector = []
values = ['a','b','c','d','e','f','g']
for i in range(0,len(values)):
    vector.append(values[i])

Hoe doe je dit in 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

Antwoord 1, autoriteit 100%

Toevoegen aan een object in een for-lus zorgt ervoor dat het hele object bij elke iteratie wordt gekopieerd, waardoor veel mensen zeggen “R is traag” of “R-lussen moeten worden vermeden”.

Zoals BrodieGvermeld in de opmerkingen: het is veel beter om vooraf een vector van de gewenste lengte toe te wijzen, dan stel de elementwaarden in de lus in.

Hier zijn verschillende manieren om waarden aan een vector toe te voegen. Ze zijn allemaal ontmoedigd.

Toevoegen aan een vector in een lus

# 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")zou uw vraag hebben beantwoord en de tijd hebben bespaard die u nodig had om deze vraag te schrijven (maar zou u ertoe hebben gebracht slechte gewoonten te ontwikkelen). 😉

Merk op dat vector <- c()geen lege vector is; het is NULL. Als u een lege tekenvector wilt, gebruikt u vector <- character().

Wijs de vector vooraf toe voor het herhalen

Als u absoluuteen for-lus moet gebruiken, moet u de hele vector vooraf toewijzen vóór de lus. Dit gaat veel sneller dan toevoegen voor grotere vectoren.

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 

Antwoord 2, autoriteit 29%

FWIW: analoog aan python’s append():

b <- 1
b <- c(b, 2)

Antwoord 3, autoriteit 14%

Je hebt een paar opties:

  • c(vector, values)

  • append(vector, values)

  • vector[(length(vector) + 1):(length(vector) + length(values))] <- values

De eerste is de standaardbenadering. De tweede geeft je de mogelijkheid om ergens anders dan het einde toe te voegen. De laatste is een beetje verwrongen maar heeft het voordeel dat je vectoraanpast (hoewel je eigenlijk net zo gemakkelijk vector <- c(vector, values)kunt doen.

Merk op dat je in R niet door vectoren hoeft te bladeren. Je kunt ze gewoon in hun geheel bedienen.

Dit zijn ook vrij eenvoudige dingen, dus u moet enkele van de referenties.

Enkele meer opties op basis van OP-feedback:

for(i in values) vector <- c(vector, i)

Antwoord 4, autoriteit 8%

Voor de volledigheid is het toevoegen van waarden aan een vector in een for-lus niet echt de filosofie in R. R werkt beter door op vectoren als geheel te werken, zoals @BrodieG aangaf. Kijk of je code niet kan worden herschreven als:

ouput <- sapply(values, function(v) return(2*v))

Uitvoer is een vector van retourwaarden. Je kunt ook lapplygebruiken als waarden een lijst zijn in plaats van een vector.


Antwoord 5, autoriteit 5%

Soms moeten we lussen gebruiken, bijvoorbeeld als we niet weten hoeveel iteraties we nodig hebben om het resultaat te krijgen. Neem while-loops als voorbeeld. Hieronder staan methoden die u absoluut moet vermijden:

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 

Deze zijn erg inefficiënt omdat R de vector kopieert telkens wanneer deze wordt toegevoegd.

De meest efficiënte manier om toe te voegen is door index te gebruiken. Merk op dat ik het deze keer 1e7 keer laat herhalen, maar het is nog steeds veel sneller dan c.

a=numeric(0)
system.time(
  {
    while(length(a)<1e7){
      a[length(a)+1]=pi
    }
  }
)
# user  system elapsed 
# 5.71    0.39    6.12  

Dit is acceptabel. En we kunnen het een beetje sneller maken door [te vervangen door [[.

a=numeric(0)
system.time(
  {
    while(length(a)<1e7){
      a[[length(a)+1]]=pi
    }
  }
)
# user  system elapsed 
# 5.29    0.38    5.69   

Misschien heb je al gemerkt dat lengthtijdrovend kan zijn. Als we lengthmet een teller:

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

Zoals andere gebruikers genoemd, is het vooraf toe te wijzen aan de vector zeer nuttig. Maar dit is een afweging tussen snelheid en geheugengebruik als u niet weet hoeveel lussen u nodig hebt om het resultaat te krijgen.

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 

Een tussenmethode is om geleidelijk blokken resultaten toe te voegen.

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

Antwoord 6

in r, je kunt op deze manier proberen:

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"

Antwoord 7

> 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"

Antwoord 8

Wat je in de python-code gebruikt, heet een lijst in python, en het is totaal anders dan R-vectoren, als ik begrijp wat je wilt doen:

# you can do like this if you'll put them manually  
v <- c("a", "b", "c")
# if your values are in a list 
v <- as.vector(your_list)
# if you just need to append
v <- append(v, value, after=length(v))

Other episodes