2017-11-13 1 views
3

sagen, dass ich das folgende XTS-Objekt mit Bid habe und fragen Daten:entfernen sequentielle Wiederholungs Reihen von xts Objekt

Time  Bid Ask 
    00:01 10  11 
    00:02 10  11 
    00:03 11  12 
    00:04 12  13 
    00:05 10  11 
    00:06 10  11 
    00:07 10  11 

    00:08 9  12 
    00:09 2  10 
    00:10 4  5 

Ich mag folgende Ausgabe erhalten:

Time  Bid Ask 
    00:01 10  11 
    00:03 11  12 
    00:04 12  13 
    00:05 10  11 

    00:08 9  12 
    00:09 2  10 
    00:10 4  5 

Zeilen nur sein sollten entfernt, wenn sie dem vorherigen Eintrag entsprechen. Wenn es eine Bid- oder Ask-Änderung gibt, dann wird nichts entfernt, so dass Duplikate einfach nicht funktionieren.

Dies sollte ziemlich einfach sein, wie ich dies schon einmal getan habe, aber ich kann mich nicht erinnern, wie und kann es nicht finden.

Update: Ich fügte einige zusätzliche Einträge in meine Ausgangsdaten und erwartete Ausgabe.

Joshuas Sünder ist brilliant, aber es hängt von der Funktion wie rowSums geben unterschiedliche Ergebnisse, aber es bricht mit 9 12. Ich habe die RowProds Funktion aus dem MatrixStats-Paket, das funktioniert, aber offensichtlich für meine letzten 2 Zeilen fehlschlägt . Auch meine Stichprobe die Werte in Spalte eins sind kleiner als in Spalte 2. Während das sinnvoll ist, ist es kein Muss, also sollte die Funktion funktionieren, wenn das Ask weniger als das Gebot war, wo rowSums und rowProds fehlschlagen würden. Gibt es eine bessere Zeilenfunktion, die immer ein anderes Ergebnis liefert, wenn etwas anders ist, wie zum Beispiel ein Zeilenhash?

Antwort

3

Sie können dies tun, indem Sie rle() auf die Summe jeder Zeile verwenden.

x <- structure(
    c(10L, 10L, 11L, 12L, 10L, 10L, 10L, 11L, 11L, 12L, 13L, 11L, 11L, 11L), 
    .Dim = c(7L, 2L), .Dimnames = list(NULL, c("Bid", "Ask")), 
    index = structure(1:7, tzone = "", tclass = c("POSIXct", "POSIXt")), 
    .indexCLASS = c("POSIXct", "POSIXt"), .indexTZ = "", 
    tclass = c("POSIXct", "POSIXt"), tzone = "", class = c("xts", "zoo")) 
r <- rle(rowSums(x)) 

Wenn Sie die letzte Beobachtung in jeder Gruppe möchten, können Sie einfach cumsum(r$lengths) als Zeilenindex verwenden, wenn subsetting.

R> x[cumsum(r$lengths),] 
        Bid Ask 
1969-12-31 18:00:02 10 11 
1969-12-31 18:00:03 11 12 
1969-12-31 18:00:04 12 13 
1969-12-31 18:00:07 10 11 

Da Sie die erste Beobachtung jeder Gruppe wollen, müssen Sie mit dem r$lengths Vektor vorangestellt wird eine 1 (Sie immer die erste Beobachtung wollen) und dann das letzte Element r$lengths entfernen. Dann rufen Sie cumsum() auf das Ergebnis.

R> x[cumsum(c(1, head(r$lengths, -1))),] 
        Bid Ask 
1969-12-31 18:00:01 10 11 
1969-12-31 18:00:03 11 12 
1969-12-31 18:00:04 12 13 
1969-12-31 18:00:05 10 11 

Guter Fang über die Begrenzung von rowSums(). Eine robuste Lösung ist diff() die Gebote und fragt und wählen Sie die Zeilen, bei denen entweder nicht Null ist.

d <- diff(x) != 0   # rows with price changes 
d[1,] <- TRUE    # always select first observation 
g <- cumsum(d$Bid | d$Ask) # groups of repeats 
r <- rle(as.numeric(g))  # run length encoding on groups 

# now use the solution above 
x[cumsum(c(1, head(r$lengths, -1))),] 
+1

Das ist brilliant und ich brauche noch etwas Zeit, um genau herauszufinden, wie es funktioniert. Ich glaube, das rowSums ist ein wenig einschränkend, als ob die nächste Zeile 00:08 9 12 wäre, die Summe wäre bei 21 dieselbe. Zum Glück hat das matrixStats-Paket einen rowProds-Befehl, der das besser handhabt. Gibt es eine noch bessere Option, um sicherzustellen, dass Zeilen nicht versehentlich entfernt werden? Vielen Dank. – MichaelE

+0

@MichaelE: Gute Fang auf den Bug. Die aktualisierte Antwort ist robuster und führt keine zusätzlichen Abhängigkeiten ein. –

+0

Danke. diff kümmert sich um alles. – MichaelE

Verwandte Themen