Wenn ich aus Gründen der Argumentation die letzten fünf Elemente eines Vektors mit 10 Längen in Python haben möchte, kann ich den Operator "-" im Bereichsindex verwenden, also:
>>> x = range(10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x[-5:]
[5, 6, 7, 8, 9]
>>>
Was ist der beste Weg, dies in R zu tun? Gibt es einen saubereren Weg als meine derzeitige Technik, die Funktion length () zu verwenden?
> 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
>
Die Frage bezieht sich übrigens auf die Zeitreihenanalyse, bei der es oft nützlich ist, nur an aktuellen Daten zu arbeiten.
x[seq.int(to=length(x), length.out=5)]
scheint ungefähr 10x schneller zu sein als,tail()
aber ohne die Sanity Checks;x[length(x)-(4:0)]
ist noch schneller.Mit zwei weiteren Zeichen können Sie in R genau dasselbe tun:
x <- 0:9 x[-5:-1] [1] 5 6 7 8 9
oder
x[-(1:5)]
quelle
x <- 0:20; x[-5:-1]
- Dies gibt die letzten fünfzehn Elemente zurück.x[-5:]
: Bedeutet das, die ersten 5 Elemente zu überspringen oder die letzten 5 zu behalten? Wenn es der erste ist, verwendet er indirekt Ihre Länge, wie Sie hier sind (ansonsten, woher wissen Sie, welche Elemente zu überspringen sind?)tail
was Sie dann wollen.Die Ablehnung von
tail
hier allein aufgrund der Geschwindigkeit scheint nicht wirklich zu betonen, dass ein Teil der langsameren Geschwindigkeit von der Tatsache herrührt, dass das Arbeiten mit dem Schwanz sicherer ist, wenn Sie nicht sicher sind, dass die Länge von xn
die Zahl überschreitet von Elementen, die Sie unterteilen möchten: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 gibt einfach die maximale Anzahl von Elementen zurück, anstatt einen Fehler zu generieren, sodass Sie keine Fehlerprüfung selbst durchführen müssen. Ein guter Grund, es zu benutzen. Sicherer sauberer Code, wenn zusätzliche Mikrosekunden / Millisekunden für Sie bei der Verwendung keine große Rolle spielen.
quelle
Wie wäre es
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
quelle
x <- 1:10e6
Hier ist eine Funktion, um es zu tun und scheint ziemlich schnell.
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)] } }
VERWENDUNG:
test<-c(0,1,1,0,0,1,1,NA,1,1) endv(test,5) endv(LETTERS,5)
BENCHMARK:
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
quelle
Ich füge hier nur etwas Ähnliches hinzu. Ich wollte auf einen Vektor mit Backend-Indizes zugreifen, dh so etwas wie schreiben,
tail(x, i)
aber zurückkehrenx[length(x) - i + 1]
und nicht den ganzen Schwanz.Nach folgenden Kommentaren habe ich zwei Lösungen verglichen:
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
In diesem Fall scheint es also, dass selbst für kleine Vektoren im
tail
Vergleich zum direkten Zugriff sehr langsam istquelle