Dodać wartość do pustego wektora W R?

Próbuję nauczyć się R i nie mogę wymyślić, jak dołączyć do listy.

Gdyby to był Python, zrobiłbym to . . .
#Python
vector = []
values = ['a','b','c','d','e','f','g']

for i in range(0,len(values)):
    vector.append(values[i])

Jak to zrobić w 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
Author: tumultous_rooster, 2014-03-06

8 answers

Dołączenie do obiektu w pętli for powoduje, że cały obiekt jest kopiowany przy każdej iteracji, co powoduje, że wiele osób mówi "R jest wolne "lub"R pętli należy unikać".

Jako BrodieG wspomniany w komentarzach: znacznie lepiej jest wstępnie przydzielić wektor o żądanej długości, a następnie ustawić wartości elementów w pętli.

Oto kilka sposobów dodawania wartości do wektora. Wszyscy są zniechęceni.

Dodawanie do wektora w loop

# 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") odpowiedziałby na twoje pytanie i zaoszczędziłby czas potrzebny na napisanie tego pytania (ale spowodowałby, że rozwinęłbyś złe nawyki). ;-)

Zauważ, że vector <- c() nie jest pustym wektorem, lecz NULL. Jeśli chcesz mieć pusty wektor znaków, użyj vector <- character().

Wstępnie przydziel wektor przed zapętleniem

Jeśli bezwzględnie musisz użyć pętli for, powinieneś wstępnie przydzielić cały wektor przed pętlą. Będzie to znacznie szybsze niż dodawanie dla większych wektorów.

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 
 220
Author: Joshua Ulrich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-07 16:10:18

FWIW: analogicznie do Pythona append ():

b <- 1
b <- c(b, 2)
 63
Author: tumultous_rooster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-19 19:17:47

Masz kilka opcji:

  • c(vector, values)

  • append(vector, values)

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

Pierwszą z nich jest podejście standardowe. Drugi daje możliwość dołączenia w innym miejscu niż koniec. Ten ostatni jest nieco wypaczony, ale ma tę zaletę, że modyfikuje vector (choć tak naprawdę, równie łatwo można to zrobić vector <- c(vector, values).

Zauważ, że w R nie musisz przechodzić przez wektory. Można je po prostu operować w w całości.

Również, jest to dość podstawowe rzeczy, więc należy przejść przez niektóre z Bibliografia.

Kilka dodatkowych opcji na podstawie opinii OP:

for(i in values) vector <- c(vector, i)
 32
Author: BrodieG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-09 01:22:28

Tylko ze względu na kompletność, dodawanie wartości do wektora w pętli for nie jest tak naprawdę filozofią w R. R działa lepiej, operując na wektorach jako całości, jak zauważył @BrodieG. Sprawdź, czy Twój kod nie może być przepisany jako:

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

Wyjście będzie wektorem wartości zwrotnych. Możesz również użyć lapply, jeśli wartości są listą zamiast wektora.

 18
Author: antoine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-14 20:16:35

Czasami musimy używać pętli, na przykład, gdy nie wiemy, ile iteracji potrzebujemy, aby uzyskać wynik. Weźmy pętle while jako przykład. Poniżej znajdują się metody, których absolutnie należy unikać:

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 

Są one bardzo nieefektywne, ponieważ r kopiuje wektor za każdym razem, gdy się dołącza.

Najskuteczniejszym sposobem dodawania jest użycie indeksu. Zauważ, że tym razem pozwoliłem iteracji 1e7 razy, ale i tak jest znacznie szybszy niż c.

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

To jest dopuszczalne. I możemy zrób to nieco szybciej, zastępując [ na [[.

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

Może już zauważyłeś, że length może być czasochłonne. Jeśli zamienimy length na licznik:

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

Jak wspomnieli inni użytkownicy, wstępna alokacja wektora jest bardzo pomocna. Ale jest to kompromis między szybkością a zużyciem pamięci, jeśli nie wiesz, ile pętli potrzebujesz, aby uzyskać wynik.

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 

Metodą pośrednią jest stopniowe dodawanie bloków wyników.

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
 10
Author: lovetl2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-19 16:16:50

W R, można wypróbować w ten sposób:

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
Author: Sowmya S. Manian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-04 20:04:39
> 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
Author: Surya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-21 23:52:21

To, czego używasz w kodzie Pythona, nazywa się listą w Pythonie i różni się od wektorów R, Jeśli dostanę to, co chcesz zrobić:

# 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))
 0
Author: Youssef Snoussi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-15 00:44:38