ベクトルの最後の値にアクセスする方法は?


289

1つまたは2つのレベルのデータフレームにネストされているベクトルがあるとします。length()関数を使用せずに最後の値にアクセスするための迅速でダーティーな方法はありますか?PERLの$#特別な変数の何か?

だから私は次のようなものが欲しいです:

dat$vec1$vec2[$#]

の代わりに

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

1
私は決してRのエキスパートではありませんが、簡単なGoogleがこれを確認しました:< stat.ucl.ac.be/ISdidactique/Rhelp/library/pastecs/html/… >「最後の」関数のようです。
benefactual


1
MATLABには「myvariable(end-k)」という表記があり、kは(length(myvariable)-k)番目の要素を返すベクトルの長さよりも小さい整数です。それはR.で持っていいだろう
EngrStudent

回答:


368

私はtail関数を使用します:

tail(vector, n=1)

良い点tailは、x[length(x)]イディオムとは異なり、データフレームでも機能することです。


5
ただし、x [length(x [、1])、]はデータフレームまたはx [dim(x)[1]、]で機能します
kpierce8

29
データフレームの場合、length(x)== ncol(x)となるため、間違いです。dim(x)[1]は、よりわかりやすくnrow(x)と記述できます。
ハドリー2009

2
@hadley-kpierce8の提案x[length(x[,1]),]は間違っていません(xサブセットのコンマに注意してください)が、確かに厄介です。
jbaums 2015

4
以下の私のベンチマークは、これがx[length(x)]大きいベクトルの場合、平均で30倍よりも遅いことを示していることに注意してください!
匿名の

1
ただし、ベクターからデータを追加したい場合は機能しませんtail(vector, n=1)-tail(vector, n=2)
Andreas Storvik Strauman

179

美的ではなくパフォーマンス指向の観点からこれに答えるために、上記の提案をすべてベンチマークに通しました。正確には、私は提案を検討しました

  • x[length(x)]
  • mylast(x)ここで、mylastC ++関数は、Rcppを介して実装されています
  • 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)およびよりもかなり遅いですx[length(x)]。以来mylast(x)より遅いですx[length(x)]:(むしろ、それが習慣だと優雅に空のベクターを処理しない)と何のメリットを提供していない、私は答えは明らかだと思います使用x[length(x)]


11
^ O(1)ソリューションは、この質問の唯一の受け入れられる答えでなければなりません。
クワメ2017年

2
すべてのそれらのanon +1のタイミングをとってくれてありがとう!
Sam

1
試したところ、mylastR=function(x) {x[length(x)}mylastx[length(x)]
Rcpp

115

Pythonのx [-1]表記と同じくらい良いものを探しているなら、あなたは運が悪いと思います。標準のイディオムは

x[length(x)]  

しかし、これを行う関数を書くのは簡単です。

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

Rのこの欠けている機能も私を困らせます!


3
関数の例+1を提供する素晴らしいアイデア
H.Latte

最後の要素だけでなく、ベクトルの最後のいくつかの要素が必要な場合は、このソリューションを適用するときに複雑なことを行う必要がないことに注意してください。Rのベクトルを使用すると、ニート物事が最後の四つの要素を取得したいと行うことができますx行うことでx[length(x)-0:3]
J.ミニ

46

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。)


7
以下の私のベンチマークは、これがx[length(x)]大きいベクトルの場合、平均で30倍よりも遅いことを示していることに注意してください!
匿名の

19

dplyrのパッケージには、機能が含まれてlast()

last(mtcars$mpg)
# [1] 21.4

4
これは基本的にx[[length(x)]]再び要約されます。
Rich Scriven

6
フードの下でも同様ですが、この答えを使用するlast()と、独自の関数を記述してその関数をどこかに保存する必要はありません。関数の可読性が向上し、移植性がCRANに由来するため、他の誰かがコードを実行できます。
Sam Firke

1
mtcars$mpg %>% last好みに応じて、と書くこともできます。
キース・ヒュージット16

1
@RichScriven残念ながら、それよりもかなり遅いx[[length(x)]]です!
匿名の

18

次のコードを使用して、663,552行のデータフレームでこれら2つのアプローチをベンチマークしました。

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)2番目のケースをテストしないのはなぜですか?私にとっての主な利点は、tail1行で記述できることです。;)
mschilli 2014

13

別の方法は、反転したベクトルの最初の要素を取ることです:

rev(dat$vect1$vec2)[1]

7
これは高価ですが!
フェリペジェラール

1
これは、計算コストが入力の長さに比例する操作であることに注意してください。つまり、O(n)ですが、O(1)ではありません。実際の数値については、以下の私のベンチマークも参照してください。
匿名の

@anonymousイテレータを使用しない限り
James

@ジェームズそうです。しかし、その場合、コードも機能しません。イテレータとは、イテレータパッケージによって提供されるものを意味する場合、(1)[1]最初の要素にアクセスするために使用できません。(2)revイテレータに適用できる間、期待どおりに動作しません。イテレータオブジェクトを次のように扱います。そのメンバーのリストとそれを逆にします。
匿名の


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)]まだかなり面倒です。
グレゴール・トーマス

1
次のように書くことができますnrow
フランクダーノンコート2017

2
注:とは異なりnrowNROWではベクトルを1列の行列として扱います。
PatrickT 2018

3

xtsパッケージはlast関数を提供します:

library(xts)
a <- 1:100
last(a)
[1] 100
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.