Zeit-Druck Datensatz - "intelligent" kürzen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Rene-AC
User
Beiträge: 5
Registriert: Montag 1. Juni 2015, 09:25

Moin,

Ich hab folgendes Problem:

Ich möchte eine Zeit/Volt Datenserie kürzen. Aber ich möchte nich einfach nur rolling average (oder Ähnliches) verwenden , sondern, in dem Bereich indem sich die Spannung kaum bis nicht ändert, viele Datenpunkte einsparen, in Bereich wo sich die Spannung aber stark/schnell ändert will ich möglichst viele Datenpunkte erhalten.
(Die Rohdaten haben bis zu eine halbe million Datenpunkte und damit muss im Anschluss simuliert werden, und da bin ich dann durch die Rechenzeit auf maximal 5.000 Punkte, besser 500 beschränkt)

Als Beispiel zwei Ausschnitte:
0.000 0.810
0.004 0.810
0.008 0.810
0.012 0.810
0.016 0.810
0.020 0.810
0.024 0.810
0.028 0.809
0.032 0.809
0.036 0.809
0.040 0.809
0.044 0.809
0.048 0.809
0.052 0.809
0.056 0.809
0.060 0.809
0.064 0.809
0.068 0.809
0.072 0.809
0.076 0.809
0.080 0.809
0.084 0.809
0.088 0.809
0.092 0.809
0.096 0.809
0.100 0.808
Man sieht, das in dem Bereich der ersten 0.100 ms sich die Spannung nahezu nicht ändert, hier könnte man dann den Bereich zu folgendem Teil kürzen:
0.004 0.810
0.028 0.809
0.100 0.808
Im Gegensatz dazu:
50.000 5.136
50.004 5.142
50.008 5.148
50.012 5.154
50.016 5.160
50.020 5.166
50.024 5.172
50.028 5.178
50.032 5.184
50.036 5.190
50.040 5.196
50.044 5.202
50.048 5.208
50.052 5.214
50.056 5.220
Hier würde ich am fast gar keinen Datenpunkt kürzen.

Ich würde eigentlich vermuten, dass es zu so etwas banalem eigentlich schon was in pandas gibt, aber ich kann nichts passendes finden.

Ich hoffe ihr könnt mir weiter helfen.
einfachTobi
User
Beiträge: 492
Registriert: Mittwoch 13. November 2019, 08:38

Du kannst mit DataFrame.pct_change() die prozentuale Änderung ermitteln und diese mit sinnvollen Grenzwerten abgleichen. Ungetestet:

Code: Alles auswählen

df = pd.DataFrame({"werte":[1.0, 5, 1.0, 1.15, 1.1, 1.05, 2, 3]})
print(df)
print(df[~((df.werte.pct_change() <= 0.2) & (df.werte.pct_change() >= -0.2))])
Natürlich kannst musst du die Grenzen anpassen. Durch das Negieren und die &-Verknüpfung müsste bspw. der erste Wert erhalten bleiben.

Ergänzung: Wenn deine Berechnung so lange dauert vermute ich eher woanders das Problem, als in der Menge der Daten. Gewagte Vermutung: Du iterierst über das DataFrame.
Rene-AC
User
Beiträge: 5
Registriert: Montag 1. Juni 2015, 09:25

Hey Tobi,

vielen dank für die Antwort.
Funktioniert perfekt und ist deutlich schneller als mein while_loop ansatz :D

Damit ich noch was draus lerne: Nach welchem Stichwort muss ich googlen um mir details zu der Tilde ~ und deren Funktion nachlesen kann

Und dann hätte ich noch eine weitere Frage:

Um den Datensatz weiter verkleinern zu können, will ich Daten die nach einem bestimmten Event (z.B. das auftreten eines globalen Maximums) auftauchen, abgeschnitten/gelöscht werden.
Da könnte ich dann auch folgendes Verwenden:

Code: Alles auswählen

volt_column = df['volt']
max_volt = volt_column.idxmax()
df_short_cut = df[~(df.index>max_volt)]
Das funktioniert soweit ganz gut.

Zu deinem Punkt bzgl. der Simulationen: Für die Simulationen brauche ich "lediglich" die (reduzierten) Textdateien als input, und dort wird jeder Zeitpunkt als eigenständige Simulation durchgeführt; deshalb die lange Simulationszeit
Sirius3
User
Beiträge: 17761
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn man etwas über Python wissen will, dann schaut man in die Dokumentation, z.B. in den Index, wo auch Tilde aufgeführt ist: https://docs.python.org/3.9/genindex-Symbols.html. Von da aus kommt man dann zu den Bit-Operatoren: https://docs.python.org/3.9/library/std ... l#index-16
einfachTobi
User
Beiträge: 492
Registriert: Mittwoch 13. November 2019, 08:38

Du musst ja nicht jedes Zwischenergebnis an einen Namen binden. Vor allem hat `volt_column` 11 Zeichen und das Original `df['volt']` nur 10. Du sparst also noch nicht mal irgendwas. `max_volt` ist ein falscher Name, weil nicht die maximale Spannung enthalten ist, sondern der Index der maximalen Spannung.
Da tut es auch:

Code: Alles auswählen

df = pd.DataFrame({"werte":[1.0, 5, 1.0, 6, 1.1, 1.05, 2, 3]})
df.iloc[:df.werte.idxmax()] #  ggf:  df.werte.idxmax() + 1 wenn das Maximum noch drin bleiben soll
Ich meinte, dass wenn die Simulation ebenfalls in Python durchgeführt wird, vermutlich eher das Vorgehen als die Anzahl der Datenkpunkte für die benötigte Zeit sorgt. Aber sei es drum. Das Thema hier scheint ja gelöst :)
Antworten