it-swarm-pt.tech

Como acessar o último valor em um vetor?

Suponha que eu tenha um vetor aninhado em um dataframe, um ou dois níveis. Existe uma maneira rápida e suja de acessar o último valor, sem usar a função length()? Algo Alá $# var especial?

Então eu gostaria de algo como:

dat$vec1$vec2[$#]

ao invés de

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

Eu uso a função tail():

tail(vector, n=1)

O bom com tail() é que ele funciona em dataframes também, ao contrário do idioma x[length(x)].

317
lindelof

Para responder a isso não de um ponto de vista estético, mas orientado para o desempenho, coloquei todas as sugestões acima através de um benchmark. Para ser preciso, eu considerei as sugestões

  • x[length(x)]
  • mylast(x), onde mylast é uma função C++ implementada através do Rcpp,
  • tail(x, n=1)
  • dplyr::last(x)
  • x[end(x)[1]]]
  • rev(x)[1]

e aplicou-os a vetores aleatórios de vários tamanhos (10 ^ 3, 10 ^ 4, 10 ^ 5, 10 ^ 6 e 10 ^ 7). Antes de olharmos para os números, acho que deve ficar claro que qualquer coisa que se torne visivelmente mais lenta com maior tamanho de entrada (ou seja, qualquer coisa que não seja O(1)) não é uma opção. Aqui está o código que eu usei:

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]))}

Isso me dá

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

Isso exclui imediatamente qualquer coisa que envolva rev ou end, pois eles claramente não são O(1) (e as expressões resultantes são avaliadas de maneira não preguiçosa). tail e dplyr::last não estão longe de serem O(1), mas também são consideravelmente mais lentos que mylast(x) e x[length(x)]. Como mylast(x) é mais lento que x[length(x)] e não fornece nenhum benefício (em vez disso, é personalizado e não manipula um vetor vazio normalmente), eu acho que a resposta é clara: Por favor use x[length(x)].

130
anonymous

Se você está procurando algo tão agradável quanto a notação x [-1] do Python, eu acho que você está sem sorte. O idioma padrão é

x[length(x)]  

mas é fácil escrever uma função para fazer isso:

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

Esse recurso ausente no R também me irrita!

100
Gregg Lind

Combinando as ideias de Lindelof e Gregg Lind:

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

Trabalhando no Prompt, eu costumo omitir o "n=", ou seja, tail(x, 1).

Ao contrário de last do pacote pastecs, head e tail (de utils) funcionam não apenas em vetores, mas também em quadros de dados, etc., e também podem retornar dados "sem primeiro/último n elementos", por ex.

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

(Note que você tem que usar head para isso, ao invés de tail.)

43
Florian Jenn

Eu apenas comparei essas duas abordagens no frame de dados com 663.552 linhas usando o seguinte código:

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 

e

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 

Então, supondo que você esteja trabalhando com vetores, acessar a posição de comprimento é significativamente mais rápido.

17
scuerda

O pacote dplyr inclui uma função last():

last(mtcars$mpg)
# [1] 21.4
16
Sam Firke

Outra maneira é pegar o primeiro elemento do vetor invertido:

rev(dat$vect1$vec2)[1]
12
James

Eu tenho outro método para encontrar o último elemento em um vetor. Diga que o vetor é 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

Ai está!

9
Akash

Sobre o quê

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

Pacote data.table inclui a função last

library(data.table)
last(c(1:10))
# [1] 10
7
Enrique Pérez Herrero

O pacote xts fornece uma função last:

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