pandas Dataframes - Problematik mit .append()

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
CSchilling
User
Beiträge: 25
Registriert: Sonntag 4. April 2021, 09:13

Guten Abend,

ich steh wieder einmal vor einer kleinen Umsetzungsproblematik....

ich lade mit pandas aus einer .csv-file Daten ein und möchte diesem Dataframe dann nach und nach neue Daten am Ende hinzufügen.
Der folgende Code-Snippet stellt nur den Code Baustein aus meinem eigentlich Programm nach und soll verdeutlichen wo mein Problem liegt.

Code: Alles auswählen

df = pd.read_csv(path2)
if df.shape[0] < max(28, 48, 14, 21):
    df_add = pd.read_csv(path1)
    df = df_add.append(df, ignore_index=True)
Muss ich nun, wenn ich neue Werte zum Dataframe hinzufüge wie bei unterhalb stehendem Code dies jedes mal in einer Variablen speichern?

Code: Alles auswählen

df = df_add.append(df, ignore_index=True)
Wenn ich nun an einer späteren Stelle im Programm die Function .append auf "df" anwende(siehe Code unterhalb) und dann danach die variable "df" mir ausgeben lasse, wurden die werte nicht hinzugefügt.

Code: Alles auswählen

df.append({'RSI': 100, 'EMA_UP': 50}, ignore_index=True)
print(df)

Vielen Dank wiedermal für Ideen und Anregungen.
Benutzeravatar
__blackjack__
User
Beiträge: 14056
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@CSchilling: `append()` fügt nicht zu dem `DateFrame` hinzu, sondern erstellt einen neuen in den die alten Daten kopiert werden und am Ende die neuen hinzugefügt werden. Ist also nicht besonders effizient.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
CSchilling
User
Beiträge: 25
Registriert: Sonntag 4. April 2021, 09:13

__blackjack__ hat geschrieben: Mittwoch 19. Mai 2021, 21:13 @CSchilling: `append()` fügt nicht zu dem `DateFrame` hinzu, sondern erstellt einen neuen in den die alten Daten kopiert werden und am Ende die neuen hinzugefügt werden. Ist also nicht besonders effizient.
ah alles klar. Dann macht das Sinn.
Gibt es denn eine effizientere Lösung dafür?
Bisher habe ich immer über eine "einfache" "with open(....) as file:" die Dateien in eine Liste eingelesen und dann im Programm die neu errechneten Werte an diese Liste angehängt.
Jedoch kam es gelegentlich zu Problemen, wenn mein Programm aufgrund eines Verbindungsverlusts zum Websocket-Server neugestartet hat. Das Problem lag daran, dass ich jedesmal wenn das Programm neustartet, die Daten aus einer csv Datei neu einlesen lasse.
Diese Daten stehen Tagsüber in einer Datei. Jedoch immer um 0:00 wird eine neue Datei erstellt. Wenn nun das Programm kurz nach 0:00 Uhr neustartet, dann sind in der kürzlich erstellen csv. Datei nicht ausreichend Daten vorhanden, deswegen müssen die restlichen Daten aus der csv. des vortages gelesen werden. Das funktioniert einfach und schnell mit pandas funktion ".append()".


Mein Programm bekommt im weitern Verlauf alle 250ms Daten von einem Websocket-Server. Alle 5 Minuten wirdaus diesen Daten ein Indikator berrechnet, welcher dann ans Ende einer Liste oder eben dem DataFrame angehängt werden soll um später im Programm damit zu arbeiten.
Das Programm hängt halt quasi in der on_message() funktion fest, solange der Websocket-Server Daten sendet.

Unterhalb habe ich einen Teil des Codes eingefügt, welcher sich mit dem "Problem" beschäftigt.

Code: Alles auswählen


.....



df = pd.read_csv(path_storage('Historical-Data', 0, symbol, interval))
if df.shape[0] < max(period_l_t, period_l_a, period_u_a, period_u_t):
    df_add = pd.read_csv(path_storage('Historical-Data', 1, symbol, interval))
    df = df_add.append(df, ignore_index=True)


def on_message(wsapp, message):
	#   Receiving data from websocket request message (every ~~250ms).
    stream_data = json.loads(message)  # raw Data send back from websocket for the recent active candle.

    #   Process the data from the websocket stream.
    if stream_data['k']['x']:  # the send datapackage does contain the candle closing data.
        rsi_5m = shortterm_rsi(float(stream_data['k']['c']),
                               df['CLOSES'].iloc[-1],
                               period_length_5m_rsi,
                               df['EMA_UP'].iloc[-1],
                               df['EMA_DOWN'].iloc[-1])
        df = df.append({'DATE': datetime.fromtimestamp(int(((stream_data['k']['t']) * 0.001))),
                        'OPEN': stream_data['k']['o'],
                        'HIGH': stream_data['k']['h'],
                        'LOW': stream_data['k']['l'],
                        'CLOSES': float(stream_data['k']['c']),
                        'EMA_UP': rsi_5m[1],
                        'EMA_DOWN': rsi_5m[2],
                        'RSI': rsi_5m[0]
                        }, ignore_index=True)
                        
        df = df.drop([0])

.....

__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Für eine solche Anwendung benutzt man einfach eine Datenbank. Zb das schon mitgelieferte & rein datei-basierte sqlite. Das Skript das da reinschreibt, wird auch nicht unterbrochen oder beendet. Will man an die Daten ran, kann man das jederzeit parallel tun.
Benutzeravatar
ThomasL
User
Beiträge: 1379
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Eventuell möchtest du auch concat anstelle von append benutzen.
https://pandas.pydata.org/docs/referenc ... das.concat
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
CSchilling
User
Beiträge: 25
Registriert: Sonntag 4. April 2021, 09:13

Danke euch für die Anregungen!

SQLite3 macht wenn ich mich die letzten Stunden richtig informiert habe, in meinem Fall eingeschränkt Sinn, jedoch würde es an anderer Stelle wiederum für neuen Aufwand sorgen. Ich "sammele" die angefallenen Daten in .csv Dateien da ich diese mit anderen Softwareprogrammen weiterverarbeite oder teilweise auch and Drittpersonen verschicke. Und die Daten sollten jeweils - für den aktuellen Tag - in einer eigenen Datei gespeichert werden, sodass Drittpersonen diese .csv Dateien einfach verwenden können.

'concat' append macht doch genau das selbe wie append, erschafft ebenfalls eine neues DataFrame Object, was ich ja eigentlich vermeiden wollte.


Trotzdem danke für eure Hilfe.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Niemand hindert dich daran, aus den SQLlite Daten CSVs zu exportieren. Es löst nur lauter Probleme, die du im Moment hast. Sowohl in Bezug auf Effizienz (was eher ästhetisch ist, solange es funktioniert) als auch Fehlerfällen. Denn SQLite ist robust. Dateien öffnen, anhängen, Schreiben deutlich weniger.
CSchilling
User
Beiträge: 25
Registriert: Sonntag 4. April 2021, 09:13

__deets__ hat geschrieben: Donnerstag 20. Mai 2021, 13:32 Niemand hindert dich daran, aus den SQLlite Daten CSVs zu exportieren. Es löst nur lauter Probleme, die du im Moment hast. Sowohl in Bezug auf Effizienz (was eher ästhetisch ist, solange es funktioniert) als auch Fehlerfällen. Denn SQLite ist robust. Dateien öffnen, anhängen, Schreiben deutlich weniger.
Du hast auf jeden Fall recht, effizienter und sicherer ist es allemal. Ich bin nur noch zu unerfahren in Bezug auf Python, Programmieren und vor allem SQL und Datenbanken.
Mein eigentliches Problem ist auch nicht das laden und schreiben der Daten. Das oberhalb beschriebene Problem mit dem laden der Daten aus zwei files, entsteht nun sehr sehr selten. Ich wollte viel mehr pandas eigentliche funktionen des rolling().mean() und rolling().std() nutzen. Dann habe ich mir gedacht, damit könnte ich ja auch gleichzeitig das sehr selten auftretende Problem des importierens der Daten lösen.
Nur habe ich dann durch meinen noch sehr Laienhaften Code und das implementieren von pandas neue Störfaktoren erzeugt, welche ich im ersten Post versucht habe zu beschreiben.

Ich werde nun erstmal wieder mit den build-in statistics funktionen arbeiten und meine uneffiziente öffnen, anhängen, schreiben Methode wählen. Damit hat es bereits "gut" funktioniert.

Ich muss mir erstmal ein Verständnis zu Datenbanken und SQL anschaffen, damit ich das besser in meine Programme implementieren kann.


Danke auf jeden Fall für die Überzeugungsarbeite ;-)
Antworten