R의 빈 벡터에 값을 추가 하시겠습니까?


160

R을 배우려고하는데 목록에 추가하는 방법을 알 수 없습니다.

이것이 파이썬이라면 나는 할 것이다. . .

#Python
vector = []
values = ['a','b','c','d','e','f','g']

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

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

명확하게하기 위해, 적어도 내가 올바르게 이해하면 파이썬 에서이 작업을 수행하는 방법이 아닙니다. 당신은 단순히 할 수 있습니다 vector = values; 또는 vector = vector + values를 수행 할 수 있습니다. 그러나 귀하의 사용 사례를 오해 할 수도 있습니다
Private

답변:


209

for 루프에서 객체에 추가하면 전체 객체가 반복 될 때마다 전체 객체가 복사되어 많은 사람들이 "R이 느리다"라고 말하거나 "R 루프를 피해야한다"고 말합니다.

마찬가지로 BrodieG이 코멘트에 언급 :는 원하는 길이의 벡터를 미리 할당하기 훨씬 더, 다음 루프의 요소 값을 설정.

다음은 벡터에 값을 추가하는 몇 가지 방법입니다. 그들 모두는 낙담합니다.

루프에서 벡터에 추가

# 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")귀하의 질문에 답변하고 귀하가이 질문을 작성하는 데 걸리는 시간을 절약했을 것입니다 (그러나 나쁜 습관을 개발하게했을 것입니다). ;-)

참고 vector <- c()빈 벡터 아니다; 그것은이다 NULL. 빈 문자형 벡터를 원하면을 사용하십시오 vector <- character().

반복하기 전에 벡터를 미리 할당

당신이 경우 절대적으로해야한다 루프를 사용하면 루프 전에 전체 벡터를 미리 할당한다. 더 큰 벡터를 추가하는 것보다 훨씬 빠릅니다.

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 

2
나는 이것을 시도했지만 내가 인쇄 할 때 NULL 목록을 얻었습니다.
O.rka

6
비 효율성에 대한 알림을 +1하지만 해결 방법 ( vector <- character(length(values)); for(...) 에 대한 세부 정보를 추가 하시겠습니까?
BrodieG

20
모든 것이 권장되지 않는 경우 이는 상당히 일반적인 패턴이므로 권장되는 사항을 강조 표시하는 것이 좋습니다.
baxx

이 시점에서, 그것은 또한 가치가 좋은 책 원이 성장 벡터에 대해 설명합니다 "R 지옥"언급 할 수있다 burns-stat.com/pages/Tutor/R_inferno.pdf을
Tjebo

62

FWIW : 파이썬의 append ()와 유사합니다 :

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

8
R 에는 append () 도 있습니다 b <- 1; b <- append(b, 2). 로 사용됩니다 . 그러나 언급했듯이 c () 는 작업을 수행하는 더 R 방법입니다.
juanbretti

31

몇 가지 옵션이 있습니다.

  • c(vector, values)

  • append(vector, values)

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

첫 번째는 표준 접근법입니다. 두 번째는 끝 이외의 장소를 추가하는 옵션을 제공합니다. 마지막은 약간 왜곡되었지만 수정의 이점이 있습니다 vector(실제로 쉽게 할 수 있습니다) vector <- c(vector, values).

R에서는 벡터를 순환 할 필요가 없습니다. 당신은 그것들을 전체적으로 조작 할 수 있습니다.

당신의 일부를 통과해야하므로 또한, 이것은 매우 기본적인 것들이며, 참조 .

OP 피드백을 기반으로 한 추가 옵션 :

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

좀 더 복잡한 것을하고 있습니다. 수정 중이므로 for-loop를 통해 추가해야합니다.
O.rka

1
@ draconisthe0ry, 왜 당신이하려는 일에 대한 자세한 내용을 제공하지 않습니까?
BrodieG

1
오 알 겠어요! for 루프에서 c (vector, values ​​[i])를 수행하는 대신 "vector = c (vector, values ​​[i])
O.rka

c벡터 대신 데이터 프레임을 추가하는 데 사용 하고 싶습니다 .
loretoparisi

18

@BrodieG가 지적한 것처럼 완전성을 위해 for 루프의 벡터에 값을 추가하는 것이 실제로 R의 철학이 아닙니다 .R은 벡터 전체를 조작하여 더 잘 작동합니다. 코드를 다음과 같이 다시 작성할 수 없는지 확인하십시오.

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

출력은 반환 값으로 구성된 벡터입니다. lapply값이 벡터 대신 목록 인 경우 에도 사용할 수 있습니다 .


8

예를 들어 결과를 얻는 데 필요한 반복 횟수를 모르는 경우 루프를 사용해야하는 경우가 있습니다. while 루프를 예로 들어 보겠습니다. 다음은 피해야 할 방법입니다.

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 

R은 벡터가 추가 될 때마다 벡터를 복사하기 때문에 매우 비효율적입니다.

추가하는 가장 효율적인 방법은 인덱스를 사용하는 것입니다. 이번에는 1e7 번 반복하도록했지만 여전히보다 빠릅니다 c.

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

허용됩니다. 그리고 우리는 대체하여 조금 더 빨리 만들 수 있습니다 [[[.

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

어쩌면 이미 length시간이 많이 걸릴 수 있음을 알았을 것입니다 . length카운터로 교체 하는 경우 :

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

다른 사용자가 언급했듯이 벡터를 사전 할당하는 것이 매우 유용합니다. 그러나 결과를 얻는 데 필요한 루프 수를 모르는 경우 속도와 메모리 사용량 간의 균형을 유지해야합니다.

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 

중간 방법은 점차 결과 블록을 추가하는 것입니다.

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

2

R에서는 다음과 같이 시도해 볼 수 있습니다.

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

0

파이썬 코드에서 사용하는 것을 파이썬에서 목록이라고하며, 내가 원하는 것을 얻는다면 R 벡터와 완전히 다릅니다.

# 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))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.