하나 또는 두 수준의 데이터 프레임에 중첩 된 벡터가 있다고 가정합니다. length()
함수 를 사용하지 않고 마지막 값에 액세스하는 빠르고 더러운 방법이 있습니까? PERL의 $#
특별한 var가 뭔가 있습니까?
그래서 나는 다음과 같은 것을 원합니다 :
dat$vec1$vec2[$#]
대신에
dat$vec1$vec2[length(dat$vec1$vec2)]
하나 또는 두 수준의 데이터 프레임에 중첩 된 벡터가 있다고 가정합니다. length()
함수 를 사용하지 않고 마지막 값에 액세스하는 빠르고 더러운 방법이 있습니까? PERL의 $#
특별한 var가 뭔가 있습니까?
그래서 나는 다음과 같은 것을 원합니다 :
dat$vec1$vec2[$#]
대신에
dat$vec1$vec2[length(dat$vec1$vec2)]
답변:
나는 tail
기능을 사용한다 :
tail(vector, n=1)
좋은 점 tail
은 x[length(x)]
관용구 와 달리 데이터 프레임에서도 작동한다는 것입니다 .
x[length(x[,1]),]
잘못되지 않았지만 ( x
집합 의 쉼표를 주목하십시오 ), 확실히 어색합니다.
x[length(x)]
는 더 큰 벡터의 경우 평균 30 배 보다 느리다는 것을 보여줍니다 !
tail(vector, n=1)-tail(vector, n=2)
미학적이지만 성능 지향적 인 관점에서이 문제에 답하기 위해 위의 모든 제안을 벤치 마크를 통해 제시했습니다 . 정확히 말하면 제안을 고려했습니다.
x[length(x)]
mylast(x)
mylast
Rcpp를 통해 구현 된 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)]
.
mylastR=function(x) {x[length(x)}
보다 mylast
빠르지 만 x[length(x)]
직접 쓰는 것보다 한 번 느리게 시도했다
파이썬의 x [-1] 표기법과 같은 멋진 것을 찾고 있다면 운이 없다고 생각합니다. 표준 관용구는
x[length(x)]
그러나 이것을 수행하는 함수를 작성하는 것은 쉽습니다.
last <- function(x) { return( x[length(x)] ) }
R 에서이 누락 된 기능은 나를 귀찮게합니다!
x
수행하여 x[length(x)-0:3]
.
lindelof 와 Gregg Lind의 아이디어를 결합 :
last <- function(x) { tail(x, n = 1) }
프롬프트에서 작업 할 때 일반적으로 n=
, 즉을 생략합니다 tail(x, 1)
.
달리 last
로부터 pastecs
패키지, head
및 tail
(행 utils
작업 벡터에뿐만 아니라, 데이터 프레임 등을, 또한 "데이터를 반환 할 수에서뿐만 아니라) 성 / N 요소없이 ", 즉
but.last <- function(x) { head(x, n = -1) }
( head
대신에이를 사용해야 합니다 tail
.)
x[length(x)]
는 더 큰 벡터의 경우 평균 30 배 보다 느리다는 것을 보여줍니다 !
dplyr의 패키지는 기능을 포함 last()
:
last(mtcars$mpg)
# [1] 21.4
x[[length(x)]]
다시 내려 갑니다.
last()
하고 여러 사람이 위에서 한 것처럼 해당 기능을 어딘가에 저장할 필요가 없습니다 . 다른 사람이 코드를 실행할 수 있도록 CRAN에서 제공되는 이식성과 함께 기능의 가독성이 향상되었습니다.
mtcars$mpg %>% last
선호도에 따라 로 쓸 수도 있습니다 .
x[[length(x)]]
!
방금 다음 코드를 사용하여 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
따라서 벡터로 작업한다고 가정하면 길이 위치에 액세스하는 것이 훨씬 빠릅니다.
tail(strsplit(x,".",fixed=T)[[1]],1)
두 번째 사례를 테스트하지 않는 이유는 무엇 입니까? 나에게 가장 큰 장점은 tail
한 줄로 쓸 수 있다는 것입니다. ;)
또 다른 방법은 반전 벡터의 첫 번째 요소를 취하는 것입니다.
rev(dat$vect1$vec2)[1]
[1]
첫 번째 요소에 액세스하는 데 사용할 수 없으며 (2) rev
반복자에 적용 할 수있는 동안 예상대로 작동하지 않습니다. 반복자 객체를 회원 목록과 그 반대.
패키지 기능 data.table
포함last
library(data.table)
last(c(1:10))
# [1] 10
x[[length(x)]]
다시 내려 갑니다.
무엇에 관한 것
> a <- c(1:100,555)
> a[NROW(a)]
[1] 555
NROW
많은 다른 데이터 유형에서 기대할 수있는 작업을 수행 한다는 점에 감사 하지만 a[length(a)]
OP가 피하기를 희망 하는 것과 본질적으로 동일 합니다. OP의 중첩 벡터 예제를 사용하는 dat$vec1$vec2[NROW(dat$vec1$vec2)]
것은 여전히 엉망입니다.
nrow
nrow
, NROW
1 열의 행렬 벡터로서 취급한다.