Ich möchte einen Code schreiben, um alle positiven und negativen Zahlenreihen zu zählen und zu summieren.
Zahlen sind entweder positiv oder negativ (keine Null).
Ich habe Codes mit for
Schleifen geschrieben. Gibt es eine kreative Alternative?
Daten
R.
set.seed(100)
x <- round(rnorm(20, sd = 0.02), 3)
Python
x = [-0.01, 0.003, -0.002, 0.018, 0.002, 0.006, -0.012, 0.014, -0.017, -0.007,
0.002, 0.002, -0.004, 0.015, 0.002, -0.001, -0.008, 0.01, -0.018, 0.046]
Schleifen
R.
sign_indicator <- ifelse(x > 0, 1,-1)
number_of_sequence <- rep(NA, 20)
n <- 1
for (i in 2:20) {
if (sign_indicator[i] == sign_indicator[i - 1]) {
n <- n + 1
} else{
n <- 1
}
number_of_sequence[i] <- n
}
number_of_sequence[1] <- 1
#############################
summation <- rep(NA, 20)
for (i in 1:20) {
summation[i] <- sum(x[i:(i + 1 - number_of_sequence[i])])
}
Python
sign_indicator = [1 if i > 0 else -1 for i in X]
number_of_sequence = [1]
N = 1
for i in range(1, len(sign_indicator)):
if sign_indicator[i] == sign_indicator[i - 1]:
N += 1
else:
N = 1
number_of_sequence.append(N)
#############################
summation = []
for i in range(len(X)):
if number_of_sequence[i] == 1:
summation.append(X[i])
else:
summation.append(sum(X[(i + 1 - number_of_sequence[i]):(i + 1)]))
Ergebnis
x n_of_sequence sum
1 -0.010 1 -0.010
2 0.003 1 0.003
3 -0.002 1 -0.002
4 0.018 1 0.018
5 0.002 2 0.020
6 0.006 3 0.026
7 -0.012 1 -0.012
8 0.014 1 0.014
9 -0.017 1 -0.017
10 -0.007 2 -0.024
11 0.002 1 0.002
12 0.002 2 0.004
13 -0.004 1 -0.004
14 0.015 1 0.015
15 0.002 2 0.017
16 -0.001 1 -0.001
17 -0.008 2 -0.009
18 0.010 1 0.010
19 -0.018 1 -0.018
20 0.046 1 0.046
n_of_sequence
ist nicht identisch mit dem gewünschtenSie können die Lauflängen jedes Zeichens mit
rle
vonbase
bis berechnen und so etwas tun.Bekommen
n_of_sequence
Um schließlich die Summierungen der Sequenzen zu erhalten,
quelle
Hier ist eine einfache Funktion ohne Schleife in R:
So können Sie tun:
Erstellt am 2020-02-16 durch das reprex-Paket (v0.3.0)
quelle
Hier ist eine einfache
tidyverse
Lösung ...quelle
Was Python betrifft, wird jemand eine Lösung finden, die die Pandas-Bibliothek verwendet. In der Zwischenzeit hier ein einfacher Vorschlag:
Ausgabe:
Wenn Sie separate Listen benötigen, können Sie dies tun
oder, wenn Iteratoren in Ordnung sind, einfach
(Erklärung hier )
quelle
Zwei verschiedene Lazy-Lösungen in Python mit dem Modul itertools .
Verwenden von itertools.groupby (und akkumulieren)
Verwenden von itertools.accumulate mit einer benutzerdefinierten Akkumulationsfunktion
Das
initial
Schlüsselwortargument wurde in Python 3.8 hinzugefügt. In früheren Versionen können Sieitertools.chain
das (0,0) -Tupel voranstellen:Die Ausgabe ist wie erwartet:
quelle
Ich empfehle R Paket Läufer für diese Art von Operationen. streak_run berechnet das aufeinanderfolgende Auftreten desselben Werts und sum_run berechnet die Summe im Fenster, deren Länge durch ein
k
Argument definiert wird .Hier ist die Lösung:
Unterhalb der Benchmark, um die tatsächlichen Lösungen zu vergleichen
quelle
df <- data.table(x)
eine vollständige Datenkopie. Außerdem drucken Sie die Daten in einigen Beispielen (bei denen es sich um eine weitere vollständige Kopie handelt), in anderen nicht.r = runner_streak(x); d = dt_streak(dt) ; all.equal(r, d$sum)
. Nur ein paar geprüft abertv_streak
gibt das gleiche wiedt_streak
;count_and_sum
gibt die gleichen,runner_streak
die sich von den beiden vorhergehenden unterscheiden.In R können Sie auch Folgendes tun:
quelle
Ich werfe meine [r] Antwort in den Hut, bin auf Geschwindigkeit optimiert und funktioniert mit jeder Länge von x (im Gegensatz zu der Frage, die für Länge 20 fest codiert wurde):
Um die Laufzeiten auf meinem aktuellen (sehr langsamen) Arbeitscomputer zu vergleichen, sehen Sie hier die Ausgabe meines Mikrobenchmarks unter Verwendung aller R-Lösungen in diesem Thread. Es ist nicht überraschend, dass die Lösungen, die die meisten Kopien und Konvertierungen erstellen, tendenziell langsamer sind.
-------------- BEARBEITEN -------------- @nicola hat darauf hingewiesen, dass meine Lösung für längere x-Längen nicht die schnellste ist sollte ziemlich offensichtlich sein, da ich ständig Kopien von Vektoren mache, indem ich Aufrufe wie x <- c (x, y) verwende. Ich habe nur die schnellste Lösung für Längen = 20 erstellt und nur so niedrig wie möglich mit Mikrobenchmarkierungen versehen.
Um einen faireren Vergleich zu ermöglichen, habe ich alle Versionen bearbeitet, um den Originalcode so zu generieren, wie ich es für am schnellsten halte, aber ich freue mich über Feedback dazu. Hier ist mein vollständiger Benchmarking-Code und die Ergebnisse für mein sehr langsames System. Ich freue mich über jede Rückmeldung.
Wie diese Ergebnisse zeigen, ist meine Version für andere Längen als die, für die ich optimiert habe, langsam. Je länger x ist, desto langsamer wird es bei allem über 1000 lächerlich langsam. Meine Lieblingsversion ist Ronaks, die nur die zweitschnellste auf meinem System ist. GoGonzo ist bei diesen längeren Längen bei weitem der schnellste auf meiner Maschine.
quelle
data.table
@ Ronak-Lösung ist Ihre Lösung für eine Länge von ~ 100000 um Größenordnungen langsamer.In Python können Sie nicht nur eine Klasse zum Speichern der Speichervariablen definieren, sondern auch einen Abschluss verwenden, um dasselbe zu erreichen.
Beachten Sie, dass dies nur für Python 3 funktioniert (in Python 2 können Sie die Abschlussvariable meiner Meinung nach nicht so ändern). Ähnliches gilt auch für die Summierung.
quelle
Ich denke, eine Schleife wäre einfacher zu lesen, aber nur zum Spaß, hier ist eine Lösung in Python mit Rekursion:
quelle
Hier ist ein weiterer Basis-R-Ansatz:
quelle
Reduce
eine Schleife ausgeblendet, sodass dies keine Lösung ohne Schleife ist.Eine einfache Python-Antwort ignoriert den 0-Fall:
Eine etwas ausgefeiltere Lösung kümmert sich auch um den Fall 0:
quelle