numpy.genfromtxt: Parse-Pb mit '#' und UTF-8

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
TeePy
User
Beiträge: 2
Registriert: Freitag 12. Februar 2016, 09:49

Hallo,

Folgender CSV-Daten möchte ich mit Python auslesen und manipulieren können:

Abs. Time begin;Abs. Time end;Time begin [s];Time end [s];Test case;Temperature target [°C]; Temperature measured [°C];Cycle;Subcycle;Input supply voltage [V];Ext. Sensor DC [%-pt];Computing function;Channel;Value;Min;Max;Unit
2015-11-30 11:38:37.738;2015-11-30 11:38:38.738;3273,176;3274,176;L03_PMSM_temperature;0;-38,875;540;0;14;1;Meanvalue(#3);MPT_INFO_PDU_TEMP_1.S_temp_PMSM_1;-37,986;-38;0
2015-11-30 11:38:37.738;2015-11-30 11:38:38.738;3273,176;3274,176;L03_PMSM_temperature;0;-38,875;540;0;14;1;Meanvalue(#2);MPT_INFO_PDU_TEMP_2.S_temp_PMSM_2;-38;-38;0
2015-11-30 11:38:37.738;2015-11-30 11:38:38.738;3273,176;3274,176;L03_PMSM_temperature;0;-38,875;540;0;14;1;Meanvalue(#2);MPT_INFO_PDU_TEMP_3.S_temp_PMSM_3;-38;-38;0
2015-11-30 11:38:37.738;2015-11-30 11:38:38.738;3273,176;3274,176;L03_PMSM_temperature;0;-38,875;540;0;14;1;Meanvalue(#2);MPT_INFO_PDU_TEMP_4.S_temp_PMSM_4;-37;-37;0
2015-11-30 11:38:37.738;2015-11-30 11:38:38.738;3273,176;3274,176;L03_PMSM_temperature;0;-38,875;540;0;14;1;Meanvalue(#4);MPT_INFO_PDU_TEMP_5.S_temp_PMSM_5;-37,24;-38;0


Dabei haben die Daten keinen homogen Datentyp (nur Float oder nur String z.B.) sondern jeder Spalte kann von Datentyp Float, String oder Datetime sein. Die erste Zeile beinhaltet die Namen jeder Spalte und beinhaltet "°". Auch in weitere Zeilen können nicht-ASCII-Zeichen vorkommen. CSV-Datei werden als UTF-8 enkodiert. Mein OS ist Win7 EN mit deutsch Lokalisierung => Dezimal-Zeichen für Float ist also einen "," und ".". Ab und zu können einzelene Daten fehlen; Zeile sieht dann so aus:

2015-11-30 11:38:37.738;2015-11-30 11:38:38.738;3273,176;3274,176;L03_PMSM_temperature;;;;;;;Meanvalue(#4);MPT_INFO_PDU_TEMP_5.S_temp_PMSM_5;;;0

Ziel ist also die Daten in eine Datenstruktur in Python auszulesen. Ich bin relativ neu in Python und meine erste Gedanke war die Daten in eine numpy-2D-Array zu packen. Da sporadisch manchen Daten fehlen könnten, schien mir die Funktion genfromtxt den besten Kandidat.

Mit folgender Code habe ich angefangen:
f = open(r'C:\devl\workcopies\devl_repo\Python\test.csv', 'r', encoding="UTF-8")
data = np.genfromtxt(f, delimiter=";", names=True, dtype=None, invalid_raise=False)
f.close()


Nach 4 kompletten Tag erfolglose Versuche, scheint mir die Funktion genfromtxt nicht mehr so einen guten Kandidat zu sein. Und konfus bin ich noch dazu geworden. :K Grob zusammengefasst eine Übersicht, was ich schon mal versucht habe:

1. Wenn ich die CSV-Datei als UTF-8, lesen öffne, bekomme ich folgender Fehlermeldung:
TypeError: 'in <string>' requires string as left operand, not bytes
Dabei ist es egal, ob ich encoding="UTF-8" verwende oder nicht.
Verbesserung erreiche ich die Datei als binär-Datei öffne - ja nicht schön, habe aber keine andere Ideen gehabt:
f = open(r'C:\devl\workcopies\devl_repo\Python\test.csv','rb')
data = np.genfromtxt(f, delimiter=";", names=True, dtype=None, invalid_raise=False)
f.close()


2. Es bringt uns zu der nächste Fehler:
File "C:\devl\devltools\Anaconda3\lib\site-packages\numpy\lib\_iotools.py", line 25, in _bytes_to_name
return s.decode('ascii')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 22: ordinal not in range(128)

Sieht so aus, als ich nur ASCII-Zeichen zusammen mit der Option "names=True" verwenden darf.

3. "°"-Zeichen habe ich aus der erste Zeile entfernt. Gleicher Code wird ausgeführt, nächste Meldung:
Line #2 (got 12 columns instead of 17)
Line #3 (got 12 columns instead of 17)
Line #4 (got 12 columns instead of 17)
Line #5 (got 12 columns instead of 17)
Line #6 (got 12 columns instead of 17)
Line #7 (got 12 columns instead of 17)
Line #8 (got 12 columns instead of 17)
Line #9 (got 12 columns instead of 17)
Line #10 (got 12 columns instead of 17)
Line #11 (got 12 columns instead of 17)
Line #12 (got 12 columns instead of 17)
warnings.warn(errmsg, ConversionWarning)

Es sieht so aus, dass das Zeichen "#" in der Zeile als Kommentar von gentxtfrom interpretiert wird. Durch die Parse/Splitting-Funktion werden als Zeichen nach der "#" ignoriert. Also alle "#"-Zeichen mache ich weg aus der CSV-Datei, und...

4. besser aber nicht perfekt:
Line #2 (got 16 columns instead of 17)
Line #3 (got 16 columns instead of 17)
Line #4 (got 16 columns instead of 17)
Line #5 (got 16 columns instead of 17)
Line #6 (got 16 columns instead of 17)
Line #7 (got 16 columns instead of 17)
Line #8 (got 16 columns instead of 17)
Line #9 (got 16 columns instead of 17)
Line #10 (got 16 columns instead of 17)
Line #11 (got 16 columns instead of 17)
Line #12 (got 16 columns instead of 17)
warnings.warn(errmsg, ConversionWarning)

ja, in der erster Zeile gibt es eine Spalte "Unit" zu viel, die in der Daten nicht vorkommen.

5. Spalte ";Unit" wird aus der CSV-Datei entfernt:
Na endlich: die CSV-Datei wird gelesen:
(b'2015-11-30 11:38:37.738', b'2015-11-30 11:38:38.738', b'3273,176', b'3274,176', b'L03_PMSM_temperature', 0, b'-38,875', 540, 0, 14, 1, b'Meanvalue(3)', b'MPT_INFO_PDU_TEMP_1.S_temp_PMSM_1', b'-37,986', -38, b'0')
(b'2015-11-30 11:38:37.738', b'2015-11-30 11:38:38.738', b'3273,176', b'3274,176', b'L03_PMSM_temperature', 0, b'-38,875', 540, 0, 14, 1, b'Meanvalue(2)', b'MPT_INFO_PDU_TEMP_2.S_temp_PMSM_2', b'-38', -38, b'0')....

Aber wozu die b'...'? Alle Daten sind als byte-String importiert worden....ja, es kommt daher, dass ich die CSV-Datei als binär-Datei auslese.

6. Erste Zeile komplett durch reine ASCII-Zeichenkette "a;b;c;d;e;f;g;h;i;j;k;l;m;n;o;p" ersetzt und der Code wird wieder geändert:
f = open(r'C:\devl\workcopies\devl_repo\Python\test.csv', 'r', encoding="UTF-8")
data = np.genfromtxt(f, delimiter=";", names=True, dtype=None, invalid_raise=False)
f.close()


Ergebnis: TypeError: 'in <string>' requires string as left operand, not bytes
ja, das kenn' man schon.

7. Erste Zeile ignorieren:
f = open(r'C:\devl\workcopies\devl_repo\Python\test.csv', 'r', encoding="UTF-8")
data = np.genfromtxt(f, delimiter=";", skip_header=1, dtype=None, invalid_raise=False)
f.close()


Ergebnis:
File "C:\devl\devltools\Anaconda3\lib\site-packages\numpy\lib\_iotools.py", line 219, in _delimited_splitter
line = line.split(self.comments)[0]
TypeError: Can't convert 'bytes' object to str implicitly


Schon wieder das Problem mit str und byte....


Fazit:
- ich drehe mich im Kreis und habe keine Ahnung, wie ich die Datei mit der Funktion "genfromtxt" auslesen soll. Einen CSV-Datei als binär-datei auszulesen und dann die Daten selber zu konvertieren scheint mir auch keine Lösung zu sein.

Fragen:
- Kann ich überhaupt diese Daten in der genfromtxt auslesen?
- gibt es eine andere Alternativ?

Ach und noch eins habe ich vergessen: über das Inhalt und die Form der CSV-Datei habe ich keinerlei Einfluss.

Vielleicht jemand... eine geniale Idee ????

Danke!
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@TeePy: Du hast keinen Einfluß auf die Datei, kannst aber Zeilen und Spalten entfernen??
Es ist auch komisch, dass Du zwar englische Spaltenüberschriften hast, aber dann eine deutsches Dezimalkomma?
Falls das mal eine Excel-Datei war, lese diese mit dem entsprechenden Modul (openpyxl, xlrd).
Ansonsten nimm das csv-Modul und konvertiere die Datentypen händisch. Falls Du doch ein numpy-array brauchst, hilft vielleicht numpy.from_iter.
TeePy
User
Beiträge: 2
Registriert: Freitag 12. Februar 2016, 09:49

Hallo Sirius3,

erstmals danke für den Typ mit dem csv-Modul und numpy.from_iter: werde ich gleich probiere.

Zu deiner andere Anmerkungen:
- CSV-Datei habe ich für meine Test geändert, stimmt. Allerdings die Dateien kommen aus eine andere Abteilung und verfolgen eine zwingende Spezifikation. Später soll unserem Tool schon diese Spezifikation verfolgen. Änderungen sind möglich aber sehr zäääähhh (große Firma, alles vorgegeben, alles organisiert und unflexibel... :? )
- und ja, wir haben englische Spalterbüberschriften, weil wir mit Indien/Mexico arbeiten und die Kollegen keinen Deutsch sprechen. Allerdings arbeiten wir in Deutschland, unsere OS sind Win7 DE. Aber es bringt mir auf die Idee reine Win7 mit englische regionale Einstellung für die Auswerte-PC zu probieren. Vielleicht funktioniert es besser....danke!
- und nein, leider waren die Datei vorher keine Excel-Datei.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@TeePy: gerade wenn Du mit anderen Ländern arbeitest, solltest Du dringend darauf drängen, einen Dezimalpunkt zu verwenden.
Antworten