Segmentvektor in Abhängigkeit davon, ob Werte über einem Schwellenwert in R liegen oder nicht

8

Ich habe einen langen Vektor und muss ihn gemäß einem Schwellenwert in Segmente unterteilen. Ein Segment besteht aus aufeinanderfolgenden Werten über dem Schwellenwert. Wenn die Werte unter den Schwellenwert fallen, endet das Segment und das nächste Segment beginnt dort, wo die Werte erneut den Schwellenwert überschreiten. Ich muss die Anfangs- und Endindizes jedes Segments aufzeichnen.

Unten ist eine ineffiziente Implementierung. Was ist der schnellste und geeignetste Weg dies zu schreiben? Das ist ziemlich hässlich, ich muss davon ausgehen, dass es eine sauberere Implementierung gibt.

%Vor%

BEARBEITEN: Laufzeit aller Lösungen

Danke für alle Antworten, das war hilfreich und sehr lehrreich. Ein kleiner Test aller fünf Lösungen ist unten (die vier zur Verfügung gestellten und das ursprüngliche Beispiel). Wie Sie sehen können, sind alle vier eine große Verbesserung gegenüber der ursprünglichen Lösung, aber Khashaas Lösung ist mit Abstand die schnellste.

%Vor%     
Henry David Thorough 05.07.2015, 21:35
quelle

4 Antworten

5

Ich mag for loops für die Übersetzung in Rcpp ist einfach.

%Vor%     
Khashaa 06.07.2015, 04:06
quelle
6

Hier ist eine andere Option, die meistens which verwendet. Die Start- und Endpunkte werden bestimmt, indem die nicht aufeinanderfolgenden Elemente der hit -Sequenz gefunden werden.

%Vor%

Dies ergibt etwas wie:

%Vor%

Vergleichen Sie das mit der ursprünglichen Sequenz:

%Vor%     
SimonG 05.07.2015 22:10
quelle
4
%Vor%

Erklärung

%Vor%

Berechnen Sie anhand des vektorisierten Vergleichs, welche Elemente im Eingabevektor über dem Schwellenwert liegen.

%Vor%

Berechnen Sie die Lauflängencodierung des logischen Vektors. Dies gibt eine Liste mit dem Namen 'rle' zurück, die zwei benannte Komponenten enthält: lengths , die die Länge jeder Lauflänge enthält, und values , die den Wert enthält, der diese Länge durchlaufen hat, in diesem Fall TRUE . oder FALSE , wobei ersteres ein Segment von Interesse darstellt und letzteres eine Nicht-Segment-Lauflänge darstellt.

%Vor%

Das erste Argument ist die Lauflängencodierung wie oben beschrieben. Dadurch wird das zweite Argument in einer virtuellen Umgebung ausgewertet, die aus der 'rle' -classed-Liste besteht. Dadurch werden die Komponenten lengths und values als lexikalische Variablen zugänglich.

Im Folgenden gehe ich auf den Inhalt des zweiten Arguments ein.

%Vor%

Berechne die kumulative Summe von lengths . Dies bildet die Grundlage für die Berechnung sowohl der Startindizes als auch der Endindizes jeder Lauflänge. Kritischer Punkt: Jedes Element von Cumsum repräsentiert den Endindex dieser Lauflänge.

%Vor%

Duplizieren Sie die kumulative Summe. Die erste Wiederholung dient als Basis für die Startindizes, die zweite als Ende. Ich werde diese Wiederholungen fortan als "Start-Index-Wiederholung" und "End-Index-Wiederholung" bezeichnen.

%Vor%

Dadurch wird das letzte Element am Ende der Startindex-Wiederholung entfernt und eine Null an den Anfang davon angehängt. Dies verzögert effektiv die Startindex-Wiederholung um ein Element. Dies ist notwendig, da wir jeden Startindex berechnen müssen, indem wir einen zum Endindex previous der Lauflänge hinzufügen, wobei Null als Endindex der nicht vorhandenen Lauflänge vor dem ersten verwendet wird.

%Vor%

Dies bildet eine zweireihige Matrix aus dem vorherigen Ergebnis. Die verzögerte Start-Index-Wiederholung ist die oberste Zeile, die End-Index-Wiederholung ist die untere Zeile.

%Vor%

R zyklisiert diesen Zwei-Elemente-Summanden zuerst über die Spalten hinweg, dann über die Spalten, und fügt somit eins zur obersten Zeile hinzu. Damit ist die Berechnung der Startindizes abgeschlossen.

%Vor%

Transponiert zu einer zweispaltigen Matrix. Dies ist nicht unbedingt notwendig, wenn Sie das Ergebnis als zweireihige Matrix erhalten möchten.

%Vor%

Subset nur die Segmente von Interesse. Da values ein logischer Vektor ist, der angibt, welche Lauflängen den Schwellenwert überschritten haben, können wir ihn direkt als Zeilenindexvektor verwenden.

Leistung

Ich schätze, ich schraube mich hier hin, aber die Lösung von SimonG funktioniert ungefähr doppelt so gut wie meine:

%Vor%

+1 von mir ...

    
bgoldst 05.07.2015 21:59
quelle
3

Hier ist eine andere Lösung, die ich für einfacher halte. Beachten Sie, dass Sie set.seed(10) , nicht set.seed <- 10 verwenden müssen, um den Startwert des Zufallszahlengenerators festzulegen.

%Vor%

Im Allgemeinen, wenn Sie in R schreiben, dass Sie komplizierte Schleifen schreiben und wenn Sie es wahrscheinlich falsch machen. Die meisten Probleme können in einer vektorisierten Form gelöst werden.

    
Claus Wilke 06.07.2015 02:51
quelle

Tags und Links