如何访问向量的最后一个值?

假设我有一个向量,它嵌套在一个数据框架一到两层。是否有一种不使用length()函数的快速而肮脏的方法来访问最后一个值?PERL的$#特殊var?

所以我想要这样的东西:

dat$vec1$vec2[$#]

而不是

dat$vec1$vec2[length(dat$vec1$vec2)]
454307 次浏览

如果您正在寻找像Python的x[-1]符号一样好的东西,我认为您运气不好。标准的习语是

x[length(x)]

但是写一个函数来实现这个很简单:

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

R中这个缺失的特性也让我很恼火!

我使用tail函数:

tail(vector, n=1)

tail的好处是它也适用于数据帧,不像x[length(x)]习惯用法。

结合lindelof的格雷格·林德的的思想:

last <- function(x) { tail(x, n = 1) }

在提示符处,我通常省略n=,即tail(x, 1)

与来自pastecs包的last不同,headtail(来自utils)不仅作用于向量,也作用于数据帧等,并且还可以返回数据“没有第一个/最后一个n个元素”,例如:

but.last <- function(x) { head(x, n = -1) }

(注意,你必须使用head,而不是tail。)

另一种方法是取反转向量的第一个元素:

rev(dat$vect1$vec2)[1]

我刚刚在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

所以,假设你在处理向量,访问长度位置要快得多。

我有另一种方法来寻找向量中的最后一个元素。 假设向量是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

好了!

有什么关于

> a <- c(1:100,555)
> a[NROW(a)]
[1] 555

为了回答这个问题,不是从美学的角度,而是从面向性能的角度,我把上面所有的建议都放在基准中。准确地说,我已经考虑了这些建议

  • 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

这立即排除了涉及revend的任何内容,因为它们显然不是O(1)(并且结果表达式以非惰性方式求值)。taildplyr::lastO(1)相差不远,但它们也比mylast(x)x[length(x)]慢得多。由于mylast(x)x[length(x)]慢,并且没有提供任何好处(更确切地说,它是自定义的,不能优雅地处理空向量),我认为答案是明确的:end1。

data.table包含last函数

library(data.table)
last(c(1:10))
# [1] 10

dplyr包包含一个函数last():

last(mtcars$mpg)
# [1] 21.4

xts包提供了一个last函数:

library(xts)
a <- 1:100
last(a)
[1] 100