.CSV-Dateien auslesen und Header automatisch überspringen

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
JesusIsMyLord
User
Beiträge: 12
Registriert: Mittwoch 24. Oktober 2018, 16:17

Hallo,

ich möchte aus einer .csv-Datei eine Matrix (np.array) lesen und damit dann weiter arbeiten...Problem ist, dass ich manchmal bei den Dateien einen Header habe und manchmal nicht. Ich kann das nicht festlegen und muss es daher abfangen!

Bisher lese ich die Dateien wie folgt aus:

Code: Alles auswählen

datei=genfromtxt("%s"%datei_name, delimiter=',')
Ich benutze bewusst dieses Format, da ich dann gleich die Zahlen in meinem benötigten np.array-Format habe. Den Dateiname erhalte ich aus einer anderen Funktion....das ganze funktioniert auch Einwandfrei....
Wenn allerdings einen Header in der Datei habe, bekomme ich eine Fehlermeldung....
in genfromtxt
raise ValueError(errmsg)
ValueError: Some errors were detected !
Line #19 (got 100 columns instead of 2)
usw....
Mir ist auch völlig klar woher der Fehler kommt...Er liest ja den Header mit nur 2 columns, nach dem Header sind es halt mehr columns und dann kann dies nicht ordentlich in den array geschrieben werden....
Den header kann ich ja wie folgt überspringen (in diesem Fall ist er 18 Zeilen lang):

Code: Alles auswählen

datei=genfromtxt("Test.csv", delimiter=',', skip_header=18)
Wenn ich allerdings mit dieser Methode eine Datei ohne Header einlese, schnippelt er mir die ersten 18 Zeilen weg, was bei meiner Anwendung nicht sein darf!

Eine andere Methode geht über den csv reader, dies ist allerdings umständlich, da ich dann meine erhaltene Liste erst in einen Array und dann die einzelnen Einträge in Float umändern muss....(bei pandas ist das ja so wie ich es verstanden habe auch so):

Code: Alles auswählen

f = open("%s"%bennennung, "r")
    reader=csv.reader(f, delimiter=",")
    a = list()
    for row in reader:
        a.append(row)
    f.close()
    datei = np.array(a)
    datei=datei.astype(float)
Vom Prinzip her geht das....Dann könnte ich eben im Nachhinein mir die ersten Werte anschauen und dadurch bestimmen, ob ich eine Datei mit oder ohne Header habe und diese dann mit einer if/else Anweisung weiter verarbeiten...

Meine Frage ist, ob ich das Thema irgendwie anders lösen kann, indem ich davor bestimme, ob die Datei nen Header hat oder nicht und sie dann mit "genfromtxt" auslesen kann. Dies wäre wesentlich komfortabler. Gibt es da was, was ich in der Doku von numpy.genfromtxt übersehen habe?
Meine einzige andere Idee wäre eben über den csv-Reader nur einen Teil auslesen zu lassen und zu bestimmen ob es ne Datei mit oder ohne Header ist und dann entsprechend mit genfromtxt einzulesen (und bei Bedarf den Header überspringen)...Das wäre allerdings eher unelegant und ich könnte auch gleich wie oben einfach einlesen, in array umwandeln, in float umwandeln und natürlich den Header wegschneiden.....
Hat jemand eine elegantere Idee?
Zusammenfassung:
1. Bestimmen ob csv-Datei header hat oder nicht!
2. csv-Datei (bei Bedarf ohne Header) einlesen (am Besten als np.array)
Hat jemand eine andere Idee, wie die von mir genannten?

Vielen Dank für die Unterstützung
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Also ich würde da eine Funktion schreiben die versucht zu bestimmen wie viele Zeilen der Header hat, und dann `genfromtxt()` verwenden.

Was denkst Du eigentlich was "%s" % datei_name bewirkt? Das sieht sehr unsinnig aus.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

numpy.genfromtxt hat noch einen Parameter
invalid_raise : bool, optional
If True, an exception is raised if an inconsistency is detected in the number of columns. If False, a warning is emitted and the offending lines are skipped.
Vielleicht hilft der ja?
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
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn es entweder 0 Zeilen oder 18 Zeilen Header gibt und sonst keine anderen Varianten, könnte man einfach versuchen ohne Header zu lesen und falls ein ValueError kommt, das ganze nochmal mit skip_header=18.

Eleganter wäre es, anhand der ersten Zeilen zu bestimmen, wie viele Headerzeilen es gibt. Wie genau, das kommt natürlich auf die Art des Headers an.

Code: Alles auswählen

from itertools import chain
with open(filename) as lines:
    for line in lines:
        if not is_header_line(line):
            break
    # eine Zeile zu viel gelesen!
    lines = chain([line], lines)
    data = np.genfromtxt(lines, delimiter=',')
JesusIsMyLord
User
Beiträge: 12
Registriert: Mittwoch 24. Oktober 2018, 16:17

Hallo,

@__blackjack__ Ok, dass wäre auch in etwa meine Methode gewesen. Meinst du vom Ansatz her was in die Richtung von Sirius3 oder an was hast du gedacht?
Sonst werde ich mal was basteln, bis es funktioniert!
Zum Thema "%s" % datei_name: Meiner Meinung und Erfahrung nach ist das ein Platzhalter für einen String. Diesen String (datei_name) erhalte ich über eine andere Funktion. Dieser String ist der Dateiname, beziehungsweise Dateipfad der zu öffnenden Datei. Da ich mehre Dateien einlese mit verschiedenen Dateinamen/-pfaden erschien mir das als sinnvolle Möglichkeit. Gibt es eine bessere/andere? Zumindest funktioniert es, aber für eine Anregung zur Verbesserung wäre ich sehr dankbar!

@ThomasL Damit habe ich es auch schon probiert, kam allerdings auf keinen grünen Zweig, da der Header ja am Anfang steht und er dadurch den falschen Teil wegschneidet/übergeht....Bei "genfromtxt" geht er ja im Prinzip davon aus, dass die gesamte Datei die Formatierung (gemeint ist Anzahl columns) wie in der ersten column, die er einliest, hat. So zumindest mein Wissen. Er sieht also folglich alles was nicht Header ist, als Ausnahme und überspringt es.

@Sirius3 Das ist ein interessanter Ansatz, an dem ich mich mal ausprobiere. Vielen Dank! Ich melde mich, wenn ich was Vorzeigbares habe.

Vielen Dank bis dahin schon mal.

Viele Grüße
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@JesusIsMyLord: Klar funktioniert '%s' % datei_name, aber das ist genau so überflüssig wie auf Zahlwerte immer noch mal eine Null zu addieren. Kann man machen, macht aber keinen Sinn. Und Leser fragen sich dann was das soll.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
JesusIsMyLord
User
Beiträge: 12
Registriert: Mittwoch 24. Oktober 2018, 16:17

Da hast du natürlich recht! Das sind meine persönlichen Überbleibsel aus C-Programmierung :lol:

Zum ursprünglichen Thema: Ich habe festgestellt, dass bei allen Dateien, die einen Header besitzen, die Länge des Headers immer gleich ist, weshalb ich jetzt einfach am Anfang nur die erste Zeile auslese, bestimme ob die Datei einen Header hat und dementsprechend lese ich mit einer if/else - Anweisung die Datei aus und überspringe eben bei Bedarf den Header!

Herzlichen Dank an alle für die Unterstützung und die Ratschläge!
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@JesusIsMyLord: Ich sehe nicht wie das ein Überbleibsel aus C-Programmierung sein kann, denn dort wäre das genau so unsinnig. Und noch ein bisschen komplizierter da einen überflüssigen `sprintf()`/`snprintf()` (oder die v…-Variante(n)) einzubauen statt den Zeiger auf die Zeichenkette direkt zu verwenden oder sie einfach zu kopieren, falls man das original nicht ”besitzt” oder es (nicht) verändert werden soll.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten