获取向量的最后n个元素.有没有比使用length()函数更好的方法?

Tho*_*wne 71 indexing r

如果为了论证,我想要Python中10长度向量的最后五个元素,我可以在范围索引中使用" - "运算符,这样:

>>> x = range(10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x[-5:]
[5, 6, 7, 8, 9]
>>>
Run Code Online (Sandbox Code Playgroud)

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
> 
Run Code Online (Sandbox Code Playgroud)

这个问题与btw的时间序列分析有关,通常只对最近的数据有用.

Jor*_*eys 102

看到?tail?head一些方便的功能:

> x <- 1:10
> tail(x,5)
[1]  6  7  8  9 10
Run Code Online (Sandbox Code Playgroud)

为了论证的缘故:除了最后五个元素之外的所有元素都是:

> head(x,n=-5)
[1] 1 2 3 4 5
Run Code Online (Sandbox Code Playgroud)

正如@Martin Morgan在评论中所说,还有另外两种可能性比尾部解决方案更快,以防你必须在1亿个值的向量上进行一百万次.为了便于阅读,我会选择尾巴.

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     
Run Code Online (Sandbox Code Playgroud)

基准代码:

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)
)
Run Code Online (Sandbox Code Playgroud)

  • utils ::: tail.default的实现是`x [seq.int(to = length(x),length.out = 5)]`,它似乎比`tail()`快约10倍但没有理智检查; `x [length(x) - (4:0)]`更快. (6认同)
  • @Nick:的确如此.在长度为1e6且重复1000次的向量上,它慢约0.3秒.想象一下,你节省的0.3秒你可以做些什么... (4认同)

Sac*_*amp 6

你可以在 R 中用另外两个字符做同样的事情:

x <- 0:9
x[-5:-1]
[1] 5 6 7 8 9
Run Code Online (Sandbox Code Playgroud)

或者

x[-(1:5)]
Run Code Online (Sandbox Code Playgroud)

  • Sacha,我不认为您的回答具有概括性。您的代码示例所做的是删除前 5 个结果,而不是保留最后五个结果。在这个例子中,它是一样的,但以下不起作用:`x &lt;- 0:20; x[-5:-1]` - 返回最后十五个元素。 (11认同)
  • 啊对了,我不知道 python 并假设它意味着跳过前 5 个。那么 `tail` 就是你想要的。 (2认同)

小智 5

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
Run Code Online (Sandbox Code Playgroud)

Tail将简单地返回最大元素数而不是生成错误,因此您不需要自己进行任何错误检查.使用它的一个很好的理由.更安全的代码,如果额外的微秒/毫秒对您的使用无关紧要.


Bri*_*vis 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
Run Code Online (Sandbox Code Playgroud)