Programing

벡터의 마지막 n 개 요소를 가져옵니다.

lottogame 2020. 10. 30. 07:37
반응형

벡터의 마지막 n 개 요소를 가져옵니다. length () 함수를 사용하는 것보다 더 좋은 방법이 있습니까?


인수를 위해 Python에서 길이가 10 인 벡터의 마지막 5 개 요소를 원하면 범위 인덱스에서 "-"연산자를 사용하여 다음과 같이 할 수 있습니다.

>>> x = range(10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x[-5:]
[5, 6, 7, 8, 9]
>>>

R에서이를 수행하는 가장 좋은 방법은 무엇입니까? length () 함수를 사용하는 현재 기술보다 더 깨끗한 방법이 있습니까?

> x <- 0:9
> x
 [1] 0 1 2 3 4 5 6 7 8 9
> x[(length(x) - 4):length(x)]
[1] 5 6 7 8 9
> 

이 질문은 최근 데이터에 대해서만 작업하는 것이 유용한 시계열 분석 btw와 관련이 있습니다.


참조 ?tail?head몇 가지 편리한 기능 :

> x <- 1:10
> tail(x,5)
[1]  6  7  8  9 10

인수를 위해 마지막 5 개 요소를 제외한 모든 것은 다음과 같습니다.

> head(x,n=-5)
[1] 1 2 3 4 5

@Martin Morgan이 의견에서 말했듯이, 1 억 개의 값으로 구성된 벡터에서이 작업을 백만 번 수행해야하는 경우 꼬리 솔루션보다 빠른 다른 두 가지 가능성이 있습니다. 가독성을 위해 꼬리를 사용합니다.

test                                        elapsed    relative 
tail(x, 5)                                    38.70     5.724852     
x[length(x) - (4:0)]                           6.76     1.000000     
x[seq.int(to = length(x), length.out = 5)]     7.53     1.113905     

벤치마킹 코드 :

require(rbenchmark)
x <- 1:1e8
do.call(
  benchmark,
  c(list(
    expression(tail(x,5)),
    expression(x[seq.int(to=length(x), length.out=5)]),
    expression(x[length(x)-(4:0)])
  ),  replications=1e6)
)

의 승인 tail속도에 따라 여기에 혼자 정말 당신이 x의 길이가 초과 할 확실하지 않으면 꼬리와 작업에 안전하다는 사실에서 오는 느린 속도의 그 부분을 강조하지 않는 것 n, 수 하위 집합을 만들려는 요소 :

x <- 1:10
tail(x, 20)
# [1]  1  2  3  4  5  6  7  8  9 10
x[length(x) - (0:19)]
#Error in x[length(x) - (0:19)] : 
#  only 0's may be mixed with negative subscripts

Tail은 오류를 생성하는 대신 최대 요소 수를 반환하므로 직접 오류를 검사 할 필요가 없습니다. 그것을 사용하는 큰 이유. 추가 마이크로 초 / 밀리 초가 사용하는 데별로 중요하지 않은 경우 더 안전한 코드입니다.


두 개의 문자를 더 사용하여 R에서도 똑같은 일을 할 수 있습니다.

x <- 0:9
x[-5:-1]
[1] 5 6 7 8 9

또는

x[-(1:5)]

어때요 rev(x)[1:5]?

x<-1:10
system.time(replicate(10e6,tail(x,5)))
 user  system elapsed 
 138.85    0.26  139.28 

system.time(replicate(10e6,rev(x)[1:5]))
 user  system elapsed 
 61.97    0.25   62.23

여기에 그것을 수행하는 기능이 있으며 합리적으로 빠르게 보입니다.

endv<-function(vec,val) 
{
if(val>length(vec))
{
stop("Length of value greater than length of vector")
}else
{
vec[((length(vec)-val)+1):length(vec)]
}
}

용법:

test<-c(0,1,1,0,0,1,1,NA,1,1)
endv(test,5)
endv(LETTERS,5)

기준:

                                                    test replications elapsed relative
1                                 expression(tail(x, 5))       100000    5.24    6.469
2 expression(x[seq.int(to = length(x), length.out = 5)])       100000    0.98    1.210
3                       expression(x[length(x) - (4:0)])       100000    0.81    1.000
4                                 expression(endv(x, 5))       100000    1.37    1.691

여기에 관련 내용을 추가합니다. 백엔드 인덱스가있는 벡터에 액세스하고 싶었습니다. 즉 , 전체 꼬리가 tail(x, i)아니라 반환하는 것과 같은 것을 작성하고 싶었습니다 x[length(x) - i + 1].

주석에 따라 두 가지 솔루션을 벤치마킹했습니다.

accessRevTail <- function(x, n) {
    tail(x,n)[1]
}

accessRevLen <- function(x, n) {
  x[length(x) - n + 1]
}

microbenchmark::microbenchmark(accessRevLen(1:100, 87), accessRevTail(1:100, 87))
Unit: microseconds
                     expr    min      lq     mean median      uq     max neval
  accessRevLen(1:100, 87)  1.860  2.3775  2.84976  2.803  3.2740   6.755   100
 accessRevTail(1:100, 87) 22.214 23.5295 28.54027 25.112 28.4705 110.833   100

따라서이 경우에는 작은 벡터의 경우에도 tail직접 액세스에 비해 매우 느립니다.

참고 URL : https://stackoverflow.com/questions/6136613/getting-the-last-n-elements-of-a-vector-is-there-a-better-way-than-using-the-le

반응형