Seite 1 von 1

Pandas, Vergleich von zwei DataFrames

Verfasst: Montag 22. Juni 2020, 08:27
von Mr_C
Hallo Zusammen,

ich erhalte von einer Website in regelmäßigen Abständen Daten, welche ich in einem DataFrame speichere. Diese möchte ich in einer CSV-Datei speichern und zu einem späteren Zeitpunkt auswerten.

Jetzt habe ich nur das Problem, das ich die Website auslese und bereits in der CSV-Datei vorhandene Einträge nicht wieder mit abspeichern möchte. Also war mein Gedanke, die CSV-Datei zu öffnen und in einen DataFrame zu laden.

Somit haben die neuen Daten (df_neu) sowie die vorhandenen Daten (df_alt) die gleiche Struktur. Diese würde ich nun gerne vergleichen und die neuen Einträge in einem weiteren DataFrame abspeichern. Diesen kann ich dann an df_alt mit den vorhandenen Daten anhängen und wieder in der CSV-Datei speichern.

Als Lösungsansatz hatte ich bisher die merge-Funktion. Bin da aber noch nicht so durchgestiegen und mir fehlt gerade die Inspiration bzw. der Lösungsansatz :?

Jedoch glaube ich, das es hierfür eine deutlich elegantere Variante gibt. Denn ich vermute, das die Performance in ein paar Monaten ziemlich leidet, da die Datenmenge in der CSV-Datei recht groß ist.


Vielen Dank für die Unterstützung!


Ist nicht sehr Aussagefähig aber dennoch mein bisheriger Versuch: (ist nur die Teillösung zum Vergleich, die Funktionen zum laden der Inhalte funktionieren bereits :P )

Code: Alles auswählen

import pandas as pd


df_alt = pd.DataFrame()
df_neu = pd.DataFrame()
df_diff = pd.DataFrame()

df_alt = pd.read_csv("datei_alt.csv",
                 sep=";",
                 encoding="iso-8859-15",
                 header=1,
                 names=["Index", "Datum", "Zeit", "Titel", "Artikel", "URL"])

df_neu = pd.read_csv("datei_neu.csv",
                 sep=";",
                 encoding="iso-8859-15",
                 header=1,
                 names=["Index", "Datum", "Zeit", "Titel", "Artikel", "URL"])


print(df_alt)
print("****")
print(df_neu)
print("*****")

df_diff = pd.merge(df_neu, df_alt, how="inner", copy=False)
df_diff.set_index("Index")
print(df_diff)
df_diff.to_csv("diff.csv", sep=";", encoding="iso-8859-15")

Re: Pandas, Vergleich von zwei DataFrames

Verfasst: Montag 22. Juni 2020, 08:49
von __blackjack__
@Mr_C: Was ist denn der Index? Ist der in den Daten und eindeutig, oder ist das einfach ein sequentieller von Pandas generierter Index den Du mitgespeichert hast?

Sind die Daten nach Zeitstempel sortiert und kommen immer nur neue Daten?

Wenn Du auf CSV bestehst, dann wird das wohl mindestens auf immer wieder lesen der bereits vorhandenen Daten hinauslaufen. Kannst Du nicht die Daten tatsächlich in einer Datenbank speichern?

Edit: Nur aus Neugier: Was war denn der Grund für ISO-8859-15?

Re: Pandas, Vergleich von zwei DataFrames

Verfasst: Montag 22. Juni 2020, 08:58
von Mr_C
Moin blackjack,

als Index hatte ich das Datum und die Uhrzeit des jeweiligen Eintrages zusammengefügt und die Zeichen (Punkt, Doppelpunkt) entfernt.

Code: Alles auswählen

    # Index aus Datum u. Zeit erzeugen
    Index = Datum + Zeit
    Index = Index.replace(":", "")
    Index = Index.replace(".", "")
Dieser ist aber nicht zwingend so erforderlich. Es war für mich nur das einfachste, so einen eindeutigen Index zu erzeugen. Es würde vermutlich auch schon ein Vergleich ausreichend sein, ob der Index in einem DF bereits vorhanden ist. Es ist ziemlich unwahrscheinlich, das es zu einem doppelten Index kommen wird.

Ich vermute hier aber auch noch einen Fehler im lesen (und/oder schreiben). Denn beim Ausführen des Programmes wird weiterhin ein Index von Pandas generiert.

CSV-Dateien war für mich das einfachste, da ich auf dem Rechner wo das Skript läuft, keinen Datenbank Server installiert habe. Grundsätzlich gebe ich Dir Recht, wäre eine Datenbank die bessere Wahl. Aber das wäre dann die nächste Ausbaustufe :-)

Re: Pandas, Vergleich von zwei DataFrames

Verfasst: Montag 22. Juni 2020, 09:08
von paddie
Hmm..Datenbankserver brauchst du ja nicht, es würde sich vielleicht ein SQLite anbieten.? Und dann Datum und Uhrzeit als Primary Key.

Re: Pandas, Vergleich von zwei DataFrames

Verfasst: Montag 22. Juni 2020, 09:17
von einfachTobi
Ich kenen nur eine ähnliche Möglichkeit: Die DataFrames aneinander hängen und dann auf Duplikate prüfen.

Code: Alles auswählen

differences = pd.concat([df_alt, df_neu]).drop_duplicates(keep=False)
differences.to_csv(....
Ob das performantes als ein Merge ist, weiß ich nicht. Müsste man ausprobieren. Es gibt allerdings auch die fertigen Lösungen: csv-diff und csvdiff. Das wäre sicher auch einen Versuch wert.
Insgesamt scheint mir eine Datenbank da besser geeignet. Du könntest dir mal SQLite anschauen.

Re: Pandas, Vergleich von zwei DataFrames

Verfasst: Montag 22. Juni 2020, 09:34
von __blackjack__
@Mr_C: Warum Du die `Index`-Spalte erzeugt hast ist mir nicht so ganz klar. Die ist redundant und wird nicht verwendet. Wenn über den Zeitstempel verschmolzen werden soll statt immer die *ganzen* Datensätze zu betrachten, dann müsste man das bei `merge()` auch mit dem `on`-Argumnet sagen. Dem kann man aber auch mehr als eine Spalte übergeben, also beispielsweise ["Datum", "Zeit"].

Aaaaber: Die beiden Werte sollten nicht in zwei verschiedenen Spalten stehen. Das ist *ein* Wert.

Re: Pandas, Vergleich von zwei DataFrames

Verfasst: Montag 22. Juni 2020, 18:41
von Mr_C
__blackjack__ hat geschrieben: Montag 22. Juni 2020, 09:34 Warum Du die `Index`-Spalte erzeugt hast ist mir nicht so ganz klar.
Das liegt daran, das ich eigentlich einen einmaligen Index erzeugen wollte. Dabei habe ich es nun auch belassen.

Ich habe auf Euch gehört und mir mal SQLite3 angeschaut. Ich weiß gar nicht, warum ich mir das nicht schon viel eher angeschaut habe...deutlich einfacher und schöner! Besten Dank!

Um doppelte Einträge zu verhindern, habe ich nun die folgende Lösung angewendet:
Der Index (weiterhin bestehend aus Datum und Uhrzeit) ist als Primary Key und Unique angelegt.
Die Einträge speichere ich mittels INSERT OR IGNORE einfach drüber. Funktioniert bestens!

Code: Alles auswählen

    # Daten in der Datenbank aktualisieren
    sql = "INSERT OR IGNORE INTO tabelle (id, datum, zeit, titel, inhalt, url) VALUES ('" + index + "', '" + artikel[0] + "', '" + artikel[1] + "', '" + artikel[2] + "', '" + artikel[3] + "', '" + url + "')"
    c.execute(sql)  
Vielen Dank für die Unterstützung...und falls es noch eine elegantere bzw. bessere Lösung gibt, einfach melden :D

Re: Pandas, Vergleich von zwei DataFrames

Verfasst: Montag 22. Juni 2020, 18:47
von Sirius3
Man formatiert keine Werte in ein SQL-Statement hinein, sondern benutzt Platzhalter. Datum und Uhrzeit sind EIN Feld, nicht zwei.

Code: Alles auswählen

sql = "INSERT OR IGNORE INTO tabelle (datum, titel, inhalt, url) VALUES (?, ?, ?, ?)"
cursor.execute(sql, [timestamp, title, content, url])  

Re: Pandas, Vergleich von zwei DataFrames

Verfasst: Montag 22. Juni 2020, 18:52
von __blackjack__
@Mr_C: PRIMARY KEY enthält bereits UNIQUE, sonst würde es ja nicht als Primärschlüssel taugen.