Daten aus Textdatei in DataFrame importieren

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
H3llo
User
Beiträge: 20
Registriert: Montag 9. Mai 2022, 10:17

Hallo,

ich habe eine Textdatei (Beispieldatei: https://www.file-upload.net/download-14 ... e.txt.html), deren Daten ich in Python in ein DataFrame importieren möchte. Leider gibt es keine Separatoren zwischen den einzelnen Daten in der Textdatei. Ich bekomme es deshalb nicht hin, die Daten in Spalten aufzuteilen.

Hier mein Code:

Code: Alles auswählen

data = pd.read_csv(r"C:\Users\User\Desktop\51802.txt", header=None, sep="\t")
Ich habe es schon mit einem Leerzeichen als Separator versucht: Dann erhalte ich die Fehlermeldung "pandas.errors.ParserError: Error tokenizing data. C error: Expected 485 fields in line 6, saw 496" Ein Leerzeichen als Separator macht eigentlich auch so keinen Sinn, da innerhalb der einzelnen Daten auch Leerzeichen sind.

Und ich habe es mit 5 Leerzeichen als Separator versucht: Dann erhalte ich die Warnung "ParserWarning: Falling back to the 'python' engine because the 'c' engine does not support regex separators (separators > 1 char and different from '\s+' are interpreted as regex); you can avoid this warning by specifying engine='python'." und den Fehler "pandas.errors.ParserError: Expected 1 fields in line 2, saw 28. Error could possibly be due to quotes being ignored when a multi-char delimiter is used."

Mit dem Separator, den ich aktuell nutze, erhalte ich ein DataFrame, in dem alle Daten in einer Spalte stehen. Das ist auch nicht das gewünschte Ergebnis, ich erhalte aber zumindest schonmal ein DataFrame.

Ich habe die Beispieldatei etwas verfremdet. Die Fehlermeldungen und Warnungen sind hingegen von der ursprünglichen Datei. Sie werden daher vielleicht nicht die gleichen Werte beinhalten, sind aber vom Prinzip her gleich.

Wie bekomme ich ein DataFrame, in dem die Daten in Spalten aufgeteilt sind?
Sirius3
User
Beiträge: 18266
Registriert: Sonntag 21. Oktober 2012, 17:20

Das ist keine csv-Datei, also kannst Du sie auch nicht mit read_csv lesen.
Da mußt Du schon einen eigenen Parser schreiben, der die Daten zeilenweise liest und die richtigen Informationen in eine passende Datenstruktur überführt.
Es scheint einen zweizeiligen Header zu geben, dann Blöcke von je 4 Zeilen, und eine #END#-Zeile. Das ist alles nur aus den Beispieldaten herausgelesen, wie das Format tatsächlich spezifiziert ist, solltest Du am besten denjenigen fragen, der die Daten erzeugt.
All das muß Dein Parser berücksichtigen. Das gibt es nicht fertig, diese Logik muß Du selbst programmieren.
H3llo
User
Beiträge: 20
Registriert: Montag 9. Mai 2022, 10:17

Hallo Sirius,

erstmal Danke für deine Antwort!

Textdateien kann man tatsächlich auch mit read_csv einlesen - siehe https://pandas.pydata.org/docs/user_gui ... text-files.

Ziel ist es, möglichst vorhandene Funktionen zu benutzen, um die Daten zu strukturieren. Loops sollen wo möglich vermieden werden, um eine hohe Performance zu erhalten.

Zu meinem aktuellen Stand: Ich habe es nun hin bekommen, die Daten schonmal zumindest etwas zu trennen. Hier der Code:

Code: Alles auswählen

data = pd.read_csv(r"C:\Users\User\Desktop\51802.txt", header=None, names=list(range(0,500)), engine="python", sep="     ")
Ich habe den ersten 500 Spalten einen Namen gegeben, sodass die Daten auf jeden Fall in einer benannten Spalte stehen. Das beseitigt den Fehler "pandas.errors.ParserError: Error tokenizing data. C error: Expected 485 fields in line 6, saw 496".

Dann habe ich die Engine auf "Python" gesetzt. Das ist nötig, um einen Separator angeben zu können, der mehr als ein Zeichen lang ist. Ich habe dann 5 Leerzeichen als Separator eingegeben.

So habe ich die Daten im DataFrame getrennt und insgesamt 10 Spalten.

Als nächstes würde ich gerne die "None" und "NaN" Werte weg haben. Die anderen Werte sollen dabei "nach links aufrücken". Soll heißen, wenn in Spalte 2 "None" oder "NaN" ist und in Spalte 3 ein Wert, soll der Wert in Spalte 2 aufrücken.

Gibt es dafür eine Funktion? Wie bekomme ich das hin?
Benutzeravatar
__blackjack__
User
Beiträge: 14031
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@H3llo: Textdateien ganz allgemein kann und sollte man nicht mit `read_csv()` einlesen. Wer das behauptet sagt auch man könne Nägel mit einem Schraubendreher in die Wand schlagen. Technisch stimmt das natürlich, aber so bekloppt ist normalerweise niemand. Du versuchst da etwas auf biegen und brechen zu machen wofür `read_csv()` nicht gedacht ist.

Und Performance ist auch kein Grund wenn man 500 Spalten anlegt und "python" als `engine` verwendet nur damit das irgendwie geht.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
snafu
User
Beiträge: 6862
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hast du es schon mal mit pandas.read_fwf() probiert? Damit kann man Textdateien verarbeiten, deren Spalten an vorab definierten Positionen beginnen. Das arbeitet also nicht mit Trennern, sondern mit Positionsangaben. Vielleicht ist das ja besser für dein Vorhaben geeignet.

Die ganzen read_*()-Funktionen lesen halt diverse Arten von tabellenartigen Dateien. Sie stellen quasi das passende Rahmenwerk für den jeweiligen Dateitypen dar. Die Optionen zum Anpassen sind jedoch nicht dafür gedacht, dass man auf Teufel komm raus immer eine ganze bestimmte read-Funktion benutzt. Wie gesagt, schau dir einfach mal an, was es neben read_csv() noch so alles gibt (siehe https://pandas.pydata.org/pandas-docs/s ... de/io.html).
Zuletzt geändert von snafu am Mittwoch 24. August 2022, 14:33, insgesamt 1-mal geändert.
Benutzeravatar
snafu
User
Beiträge: 6862
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

H3llo hat geschrieben: Mittwoch 24. August 2022, 11:37 Als nächstes würde ich gerne die "None" und "NaN" Werte weg haben. Die anderen Werte sollen dabei "nach links aufrücken". Soll heißen, wenn in Spalte 2 "None" oder "NaN" ist und in Spalte 3 ein Wert, soll der Wert in Spalte 2 aufrücken.
Das hört sich komisch an. Willst du wirklich eine zweidimensionale Tabelle haben oder reicht dir eine simple Auflistung der Werte ohne tiefere Struktur?
Benutzeravatar
kbr
User
Beiträge: 1507
Registriert: Mittwoch 15. Oktober 2008, 09:27

@H3llo: Du hast es mit einem proprietären Datenformat zu tun. Dies einzulesen klappt mit pandas allenfalls aus Zufall. Was es braucht, ist eine Beschreibung des Formats. Dann erst lassen sich die Daten sinnvoll interpretieren und in eine Form bringen, die im weiteren z.B. für pandas geeignet ist.
Antworten