벡터의 마지막 값에 액세스하는 방법은 무엇입니까?


290

하나 또는 두 수준의 데이터 프레임에 중첩 된 벡터가 있다고 가정합니다. length()함수 를 사용하지 않고 마지막 값에 액세스하는 빠르고 더러운 방법이 있습니까? PERL의 $#특별한 var가 뭔가 있습니까?

그래서 나는 다음과 같은 것을 원합니다 :

dat$vec1$vec2[$#]

대신에

dat$vec1$vec2[length(dat$vec1$vec2)]

1
나는 결코하여 R 전문가,하지만 빠른 구글이이 켜져 : < stat.ucl.ac.be/ISdidactique/Rhelp/library/pastecs/html/...가 >는 "마지막"기능이있을 나타납니다.
이익 :


1
MATLAB의 표기법은 "myvariable (end-k)"입니다. 여기서 k는 (length (myvariable) -k) 번째 요소를 반환하는 벡터의 길이보다 작은 정수입니다. R에 있으면 좋을 것입니다.
EngrStudent

답변:


368

나는 tail기능을 사용한다 :

tail(vector, n=1)

좋은 점 tailx[length(x)]관용구 와 달리 데이터 프레임에서도 작동한다는 것입니다 .


5
그러나 X [길이 (X [1])]가 dataframes에서 작동 또는 X [,] [1 (X)를 어둡게]
kpierce8

29
데이터 프레임의 경우 length (x) == ncol (x)이므로 확실히 잘못되었으며 dim (x) [1]을 더 설명 적으로 nrow (x)로 작성할 수 있습니다.
hadley

2
@hadley-kpierce8의 제안은 x[length(x[,1]),]잘못되지 않았지만 ( x집합 의 쉼표를 주목하십시오 ), 확실히 어색합니다.
jbaums

4
아래의 벤치 마크 x[length(x)]는 더 큰 벡터의 경우 평균 30 배 보다 느리다는 것을 보여줍니다 !
익명

1
그래도 벡터로부터 물건을 추가하고 싶다면 작동하지 않습니다.tail(vector, n=1)-tail(vector, n=2)
Andreas Storvik Strauman

180

미학적이지만 성능 지향적 인 관점에서이 문제에 답하기 위해 위의 모든 제안을 벤치 마크를 통해 제시했습니다 . 정확히 말하면 제안을 고려했습니다.

  • x[length(x)]
  • mylast(x)mylastRcpp를 통해 구현 된 C ++ 함수는 어디에 있습니까?
  • tail(x, n=1)
  • dplyr::last(x)
  • x[end(x)[1]]]
  • rev(x)[1]

다양한 크기 (10 ^ 3, 10 ^ 4, 10 ^ 5, 10 ^ 6, 10 ^ 7)의 랜덤 벡터에 적용했습니다. 숫자를보기 전에 입력 크기가 커질수록 눈에 띄게 느려지는 것 (즉, O (1)이 아닌 것)은 옵션이 아니라는 것이 분명하다고 생각합니다. 내가 사용한 코드는 다음과 같습니다.

Rcpp::cppFunction('double mylast(NumericVector x) { int n = x.size(); return x[n-1]; }')
options(width=100)
for (n in c(1e3,1e4,1e5,1e6,1e7)) {
  x <- runif(n);
  print(microbenchmark::microbenchmark(x[length(x)],
                                       mylast(x),
                                       tail(x, n=1),
                                       dplyr::last(x),
                                       x[end(x)[1]],
                                       rev(x)[1]))}

그것은 나를 준다

Unit: nanoseconds
           expr   min      lq     mean  median      uq   max neval
   x[length(x)]   171   291.5   388.91   337.5   390.0  3233   100
      mylast(x)  1291  1832.0  2329.11  2063.0  2276.0 19053   100
 tail(x, n = 1)  7718  9589.5 11236.27 10683.0 12149.0 32711   100
 dplyr::last(x) 16341 19049.5 22080.23 21673.0 23485.5 70047   100
   x[end(x)[1]]  7688 10434.0 13288.05 11889.5 13166.5 78536   100
      rev(x)[1]  7829  8951.5 10995.59  9883.0 10890.0 45763   100
Unit: nanoseconds
           expr   min      lq     mean  median      uq    max neval
   x[length(x)]   204   323.0   475.76   386.5   459.5   6029   100
      mylast(x)  1469  2102.5  2708.50  2462.0  2995.0   9723   100
 tail(x, n = 1)  7671  9504.5 12470.82 10986.5 12748.0  62320   100
 dplyr::last(x) 15703 19933.5 26352.66 22469.5 25356.5 126314   100
   x[end(x)[1]] 13766 18800.5 27137.17 21677.5 26207.5  95982   100
      rev(x)[1] 52785 58624.0 78640.93 60213.0 72778.0 851113   100
Unit: nanoseconds
           expr     min        lq       mean    median        uq     max neval
   x[length(x)]     214     346.0     583.40     529.5     720.0    1512   100
      mylast(x)    1393    2126.0    4872.60    4905.5    7338.0    9806   100
 tail(x, n = 1)    8343   10384.0   19558.05   18121.0   25417.0   69608   100
 dplyr::last(x)   16065   22960.0   36671.13   37212.0   48071.5   75946   100
   x[end(x)[1]]  360176  404965.5  432528.84  424798.0  450996.0  710501   100
      rev(x)[1] 1060547 1140149.0 1189297.38 1180997.5 1225849.0 1383479   100
Unit: nanoseconds
           expr     min        lq        mean    median         uq      max neval
   x[length(x)]     327     584.0     1150.75     996.5     1652.5     3974   100
      mylast(x)    2060    3128.5     7541.51    8899.0     9958.0    16175   100
 tail(x, n = 1)   10484   16936.0    30250.11   34030.0    39355.0    52689   100
 dplyr::last(x)   19133   47444.5    55280.09   61205.5    66312.5   105851   100
   x[end(x)[1]] 1110956 2298408.0  3670360.45 2334753.0  4475915.0 19235341   100
      rev(x)[1] 6536063 7969103.0 11004418.46 9973664.5 12340089.5 28447454   100
Unit: nanoseconds
           expr      min         lq         mean      median          uq       max neval
   x[length(x)]      327      722.0      1644.16      1133.5      2055.5     13724   100
      mylast(x)     1962     3727.5      9578.21      9951.5     12887.5     41773   100
 tail(x, n = 1)     9829    21038.0     36623.67     43710.0     48883.0     66289   100
 dplyr::last(x)    21832    35269.0     60523.40     63726.0     75539.5    200064   100
   x[end(x)[1]] 21008128 23004594.5  37356132.43  30006737.0  47839917.0 105430564   100
      rev(x)[1] 74317382 92985054.0 108618154.55 102328667.5 112443834.0 187925942   100

이것은 즉시 관련된 어떤 것도 배제 rev또는 end그들이 명확하지 않은 이후 O(1)(그 결과 표현이 아닌 게으른 방식으로 평가된다). tail그리고 dplyr::last멀지 않은 것은 O(1)아니지만 그들은 mylast(x)and 보다 상당히 느립니다 x[length(x)]. 때문에 mylast(x)보다 느린 x[length(x)]아무런 혜택을 제공하지 않는다 (오히려 그것의 정의와 빈 벡터 정상적으로 처리하지 않습니다), 나는 대답은 분명하다 생각 : 제발 사용x[length(x)] .


11
^이 질문에서 O (1) 해답 만이 유일하게 받아 들여 져야합니다.
Kwame

2
모든 anon +1의 타이밍을 주셔서 감사합니다!
Sam

1
나는 Rcpp mylastR=function(x) {x[length(x)}보다 mylast빠르지 만 x[length(x)]직접 쓰는 것보다 한 번 느리게 시도했다
Endle_Zhenbo

115

파이썬의 x [-1] 표기법과 같은 멋진 것을 찾고 있다면 운이 없다고 생각합니다. 표준 관용구는

x[length(x)]  

그러나 이것을 수행하는 함수를 작성하는 것은 쉽습니다.

last <- function(x) { return( x[length(x)] ) }

R 에서이 누락 된 기능은 나를 귀찮게합니다!


3
기능 예 +1을 제공하는 것이 좋습니다
H.Latte

마지막 요소가 아닌 벡터의 마지막 몇 요소를 원하면이 솔루션을 조정할 때 복잡한 작업을 수행 할 필요가 없습니다. R의 벡터화는 NEET의 일이의 마지막 네 가지 요소를 얻을처럼 수행 할 수 있습니다 x수행하여 x[length(x)-0:3].
J. Mini

46

lindelofGregg Lind의 아이디어를 결합 :

last <- function(x) { tail(x, n = 1) }

프롬프트에서 작업 할 때 일반적으로 n=, 즉을 생략합니다 tail(x, 1).

달리 last로부터 pastecs패키지, headtail(행 utils작업 벡터에뿐만 아니라, 데이터 프레임 등을, 또한 "데이터를 반환 할 수에서뿐만 아니라) 성 / N 요소없이 ", 즉

but.last <- function(x) { head(x, n = -1) }

( head대신에이를 사용해야 합니다 tail.)


7
아래의 벤치 마크 x[length(x)]는 더 큰 벡터의 경우 평균 30 배 보다 느리다는 것을 보여줍니다 !
익명

19

dplyr의 패키지는 기능을 포함 last():

last(mtcars$mpg)
# [1] 21.4

4
이것은 기본적으로 x[[length(x)]]다시 내려 갑니다.
Rich Scriven 2016 년

6
후드와 비슷하지만이 답변을 사용하면 자신의 기능을 작성 last()하고 여러 사람이 위에서 한 것처럼 해당 기능을 어딘가에 저장할 필요가 없습니다 . 다른 사람이 코드를 실행할 수 있도록 CRAN에서 제공되는 이식성과 함께 기능의 가독성이 향상되었습니다.
Sam Firke 2016 년

1
mtcars$mpg %>% last선호도에 따라 로 쓸 수도 있습니다 .
Keith Hughitt

1
@RichScriven 불행히도,보다 상당히 느립니다 x[[length(x)]]!
anonymous

18

방금 다음 코드를 사용하여 663,552 행의 데이터 프레임 에서이 두 가지 접근법을 벤치마킹했습니다.

system.time(
  resultsByLevel$subject <- sapply(resultsByLevel$variable, function(x) {
    s <- strsplit(x, ".", fixed=TRUE)[[1]]
    s[length(s)]
  })
  )

 user  system elapsed 
  3.722   0.000   3.594 

system.time(
  resultsByLevel$subject <- sapply(resultsByLevel$variable, function(x) {
    s <- strsplit(x, ".", fixed=TRUE)[[1]]
    tail(s, n=1)
  })
  )

   user  system elapsed 
 28.174   0.000  27.662 

따라서 벡터로 작업한다고 가정하면 길이 위치에 액세스하는 것이 훨씬 빠릅니다.


3
tail(strsplit(x,".",fixed=T)[[1]],1)두 번째 사례를 테스트하지 않는 이유는 무엇 입니까? 나에게 가장 큰 장점은 tail한 줄로 쓸 수 있다는 것입니다. ;)
mschilli

13

또 다른 방법은 반전 벡터의 첫 번째 요소를 취하는 것입니다.

rev(dat$vect1$vec2)[1]

7
이 될 것입니다 비싼 하지만!
Felipe Gerard

1
이것은 계산 비용이 입력 길이에서 선형 인 연산입니다. 즉, O (n) 동안 O (1)이 아닙니다. 실제 수치는 아래 벤치 마크를 참조하십시오.
익명

@anonymous 반복자를 사용하지 않는 한
James

@ 제임스 맞아. 그러나이 경우 코드도 작동하지 않습니다. 반복자에 의해 반복자 패키지가 제공하는 것을 의미하는 경우 (1) [1]첫 번째 요소에 액세스하는 데 사용할 수 없으며 (2) rev반복자에 적용 할 수있는 동안 예상대로 작동하지 않습니다. 반복자 객체를 회원 목록과 그 반대.
anonymous


10

벡터에서 마지막 요소를 찾는 다른 방법이 있습니다. 벡터가 a입니다.

> a<-c(1:100,555)
> end(a)      #Gives indices of last and first positions
[1] 101   1
> a[end(a)[1]]   #Gives last element in a vector
[1] 555

당신은 간다!


8

무엇에 관한 것

> a <- c(1:100,555)
> a[NROW(a)]
[1] 555

1
NROW많은 다른 데이터 유형에서 기대할 수있는 작업을 수행 한다는 점에 감사 하지만 a[length(a)]OP가 피하기를 희망 하는 것과 본질적으로 동일 합니다. OP의 중첩 벡터 예제를 사용하는 dat$vec1$vec2[NROW(dat$vec1$vec2)]것은 여전히 ​​엉망입니다.
Gregor Thomas

1
로 기록 될 수 있습니다nrow
프랑크 Dernoncourt

2
주 : 달리는 nrow, NROW1 열의 행렬 벡터로서 취급한다.
PatrickT

3

xts 패키지는 다음과 같은 last기능을 제공 합니다.

library(xts)
a <- 1:100
last(a)
[1] 100
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.