하나 또는 두 수준의 데이터 프레임에 중첩 된 벡터가 있다고 가정합니다. 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)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)] .
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, NROW1 열의 행렬 벡터로서 취급한다.