引数のために、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
>
質問は時系列分析に関連していますが、最近のデータでのみ作業することがしばしば有用です。
見る ?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億の値のベクトルでこれを100万回実行する必要がある場合、テールソリューションよりも高速な他の2つの可能性があります。読みやすくするために、私は尻尾を付けます。
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でさらに2つの文字を使用して、まったく同じことを行うことができます。
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]
を返すようにしたかったのです。
以下の解説に従って、2つのソリューションのベンチマークを行いました。
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
は直接アクセスと比較して非常に遅いようです。