Seite 1 von 1

Konvertierung von Dezimaltrennzeichen

Verfasst: Sonntag 7. Juni 2015, 15:08
von tine_beginner
Hallo zusammen,

ich bin neu hier im Forum und habe mich angemeldet, weil ich als python-Neuling etwas Hilfe benötige.

Ich hoffe, sämtliche vorab zusamengetragenen Reglen nun beachtet zu haben ;) Habe mich im Forum durchgeklickt, aber keine passende Lösung für mein Anliegen gefunden.

Ich habe Datensätze von mehreren Tausend CSV-Dateien. In den Datensätzen sind jeweils in 640 Spalten und 480 Zeilen nur Temperaturangaben abgespeichert, allerdings mit Komma-Dezimaltrennung (statt -4.56 1.37 liefern die Datensätze mir -4,56 1,37). Klang für mich zunächst nach einer einfachen Sache. Ich möchte die Datensätze verwenden, um zahlreiche statistische Auswertungen durchzuführen und in Grafiken darzustellen (Mittelwerte, Standardabweichung, etc.). Das ganze funktioniert natürlich nur, wenn mein eingeladener Datentyp ein float-Typ ist. Lade ich die Datei ein, erhalte ich auch die Angabe, dass die Daten von Typ "float64" sind, allerdings wird mir unter Value nur angezeigt:
[[ nan nan nan ..., nan nan nan]
[ nan nan nan ..., nan nan nan]
[ nan nan nan ..., nan nan nan]
...,
[ nan nan nan ..., nan nan nan]
[ nan nan nan ..., nan nan nan]
[ nan nan nan ..., nan nan nan]]

Der Datensatz wird also nicht als float erkannt, wegen des Komma-Dezimaltrenners.

Da es sehr viele Datensätze sind, benötige ich eine wenig rechenintensive Variante.

Mein Code sieht erstmal in etwa wie folgt aus:

Code: Alles auswählen

# Importieren von Modulen
import numpy

# Setzen des Dateinamens mit Pfad
a = 'C:/BartSimpson/temperaturen.csv'

# Einlesen der Daten in eine Variable 
b = numpy.genfromtxt(a,skip_header=9,delimiter=";")

# Die Dimensionen der Daten ausgeben
print b.shape
Könnt ihr mir dabei helfen, welche Funktion ich wie auf den Datensatz anwenden kann, damit die Daten in der Tabelle auch wirklich als float-Datentyp konvertiert werden? Ich arbeite in Spyder (Python 2.7). Ich weiß, dass es Möglichkeiten wie

Code: Alles auswählen

value = value.replace(',','.')
gibt, allerdings funktioniert das ganze bei mir irgendwie nicht. Kurz und knapp: ich will einfach alle Kommata im Datensatz durch Punkte ersetzen.

Ich bin euch um jede Hilfe dankbar!

Tine

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Sonntag 7. Juni 2015, 15:19
von BlackJack
@tine_beginner: Du könntest eine eigene Konvertierungsfunktion über das `converters`-Argument angeben, oder einen Generatorausdruck schreiben der die Kommas in jeder Zeile durch Punkte ersetzt.

Bei den Operationen die Du auf den Daten durchführen möchtest wäre vielleicht auch `pandas` ein interessantes Modul. Bei `pandas.read_csv()` kann man das Dezimalbruch-Trennzeichen direkt als Argument angeben.

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Sonntag 7. Juni 2015, 15:21
von Sirius3
@tine_beginner: und was funktioniert an replace nicht?

Code: Alles auswählen

import numpy
with open('C:/BartSimpson/temperaturen.csv') as data:
    b = numpy.genfromtxt((line.replace(',', '.') for line in data), skip_header=9, delimiter=";")
print b.shape

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Sonntag 7. Juni 2015, 15:27
von tine_beginner
Oh wow, es funktioniert :shock: aller herzlichsten Dank!

Ich habe replace in eine Funktion eingebaut gehabt und versucht die Funktion dann wieder einzubauen beim definieren der Variabel. Wahrscheinlich war das ein totales Gewusel.

Aber es funktioniert perfekt und rasend schnell! Vielen vielen Dank :)

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Sonntag 7. Juni 2015, 22:29
von tine_beginner
Hallo BlackJack,

ich will nun auf Deinen Tip hin versuchen, die unendlich vielen csv-Dateien mit dem Pandas-Modul einzuladen, um dann mit der Gesamtheit der Daten Zeitreihenanalysen durchzuführen.

Bisher sieht das ganze so aus (ohne, dass es funktioniert):

Code: Alles auswählen

# Datenimport mit Pandas
import pandas
import glob  
  
dataLists = {}  
  
# Daten einlesen  
for folder in glob.glob("C:/BartSimpson/*"):  
      
    dataLists[folder.split("/")[1]] = []  
      
    for datafile in glob.glob("C:/BartSimpson/" + "/*.csv"):  #an dieser Stelle werden ja alle csv-Dateien im Ordner angesprochen, oder?
  
        dataLists[folder.split("/")[1]].append(read_csv(datafile)) 
Ich denke, dass ich da ab der 8. Zeile wahrscheinlich auf dem Holzweg bin. Ich würde gerne die Möglichkeit nutzen, die Du vorgeschlagen hast, um die Dateien direkt mit dem korrekten Dezimalbruch-Trennzeichen zu importieren. Allerdings bin ich mir allein bei der richtigen Verwendung des panda-Moduls nicht ganz sicher.
Es wäre ein Traum, wenn ihr mir da nochmal helfen könnt. Wenn ich die ganzen Daten dann endlich im richtigen Format nutzen kann, wird es auch mit den statistischen Auswertungen funktionieren (mit einzelner Datei klappt alles).

Herzlichen Dank!

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Sonntag 7. Juni 2015, 22:40
von BlackJack
@tine_beginner: Pfade sollte man nicht mit normalen Zeichenkettenoperationen manipulieren, dafür gibt es die Funktionen in `os.path`-Modul.

Das was Du `folder` nennst muss nicht zwingend ein Verzeichnisname sein, das muss man mit der passenden Testfunktion aus dem `os.path`-Modul sicherstellen.

Die innere Schleife macht keinen Sinn da sie für jeden Datei- oder Verzeichnisnamen im ``C:/BartSimpson/``-Ordner alle CSV-Dateien *in diesem Ordner* verarbeitet, also jedes mal aufs neue die gleichen Dateien. Sofern dort überhaupt CSV-Dateien liegen.

Der Code ist ausserdem gar nicht lauffähig weil der mit einem `NameError` wegen `read_csv()` abbrechen wird.

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Sonntag 7. Juni 2015, 22:54
von tine_beginner
@BlackJack: Vielen Dank für die schnelle Antwort.

Also es fehlt pandas.read_csv().
Ansonsten bin ich grad etwas verwirrt, das mit der inneren Schleife verstehe ich aber, denke ich. Bei dem Rest muss ich grad passen. Schlimm, wenn's am Datenimport hakt :K

Danke trotzdem!

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Montag 8. Juni 2015, 06:09
von Sirius3
@tine_beginner: von welchem Rest redest Du? Davon, dass es ein Modul "os.path" gibt, mit Funktionen wie "os.path.basename" oder "os.path.join"? Oder dass Du mit "os.path.isdir(folder)" prüfen sollst, ob folder tatsächlich ein Verzeichnis ist?

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Dienstag 23. Juni 2015, 10:49
von tine_beginner
@Sirius3: Danke nochmal für den Hinweis. Doch, ich habe nun von den Modulen gelesen. Mich auch viel reingelesen. Ich verstehe nur einfach nicht, wie ich so gut 10.000 csv-Dateien einlesen kann, um damit bspw. Mittelwerte aller Dateien zu berechnen :( Kann das nicht umsetzen.
Da ich Programmieranfänger bin, fällt es mir tatsächlich nicht so leicht, dahinter zu blicken, deswegen habe ich mich an euch hier im Forum gewendet :oops: Habe ich eine Datei, dann ist das alles kein Problem.

Die Funktion "os.path.join" verwende ich, um mehr als eine Datei zu importieren, richtig?

Danke und sorry fürs langsame Lernen

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Dienstag 23. Juni 2015, 10:54
von BlackJack
@tine_beginner: Was in der Dokumentation von `os.path.join()` lässt Dich vermuten das hätte irgend etwas mit dem Importieren von Dateien zu tun? Damit setzt man Pfadteile zusammen, und zwar systemunabhängig.

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Dienstag 23. Juni 2015, 11:00
von tine_beginner
@BlackJack: :shock: ja okay, danke für den Hinweis.
Ich würde wirklich nur erstmal gerne Dateien, die alle im selben Ordner sind importieren, um sie zu bearbeiten. Da bin ich mit os.path.join dann also falsch?

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Dienstag 23. Juni 2015, 11:06
von BlackJack
@tine_beginner: Das kommt darauf an ob Du dafür an irgendeiner Stelle Pfadteile zusammenfügen musst.

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Dienstag 23. Juni 2015, 11:15
von tine_beginner
@BlackJack: was bedeutet das denn? Ich glaube nicht, dass es notwendig ist. Wie der Code oben zusammengstellt ist, funktioniert es bei mir, eine csv-Dtei korrekt zu importieren (und damit einige statistische Auswertungen und plots zu kreiieren). Das gleiche bräuchte ich eben nur für ganz viele Dateien.

Ich meine diesen:

Code: Alles auswählen

    import numpy
    with open('C:/BartSimpson/temperaturen.csv') as data:
        b = numpy.genfromtxt((line.replace(',', '.') for line in data), skip_header=9, delimiter=";")
    print b.shape
Sorry! Und vielen Dank für die Hilfe! :K

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Dienstag 23. Juni 2015, 12:20
von Sirius3
@tine_beginner: Du hast doch schon irgendetwas mit 'glob.glob' gemacht. Damit kannst Du Dir doch schon eine Liste mit Dateinamen erzeugen. Wo kommst Du also nicht weiter?

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Samstag 27. Juni 2015, 12:00
von tine_beginner
@Sirius3:
folgender Code klappt, ich bekomme die gewünschten Ergbenisse:

Code: Alles auswählen

import numpy as np
import glob

# Setzen des Dateinamens mit Pfad und dann Datei importieren
with open('C:/BartSimpson/temperaturen.csv') as data:
    b = np.genfromtxt((line.replace(',', '.') for line in data), skip_header=9, delimiter=";")

# Dimensionen der Daten ausgeben
print b.shape

# Ausgabe der Minimal- und Maximalwerte sowie Standardabweichung
print np.nanmax(b),np.nanmin(b),np.nanstd(b),np.nanvar(b),np.nanmean(b)
Dabei kommt dann sowas raus wie:

Code: Alles auswählen

np.nanmax(b),np.nanmin(b),np.nanstd(b),np.nanvar(b),np.nanmean(b)
(480, 641)
20.02 -8.05 5.01728137654 18.74632812 19.551352413958
der Inhalt der Datensätze, die ich analysieren möchte, muss eigentlich nicht in einem großen Datensatz in bestimmter Reihenfolge wieder zusammengefügt sein. Ich beötige erstmal lediglich alle enthaltenen Werte aller Datensätze, für Mittelwertberechnungen etc.

Dann versuche ich also den obigen Text auf alle im Verzeichnis vorhandenen Werte anzuwenden (die Datensätze sind csv-Dateien, in denen das Dezimaltrennzeichen ein Komma und kein Punkt ist, also z.B. "7,81" anstatt "7.81", daher belasse ich es bei der replace-Funktion):

Code: Alles auswählen

import numpy as np
import glob

# alle Daten im Datensatz ansprechen
alle = glob.glob('*.csv')

with open(alle) as data:
    b = np.genfromtxt((line.replace(',', '.') for line in data), skip_header=9, delimiter=";")

# Dimensionen der Daten ausgeben
print b.shape

# Ausgabe der Minimal- und Maximalwerte sowie Standardabweichung
print np.nanmax(b),np.nanmin(b),np.nanstd(b),np.nanvar(b),np.nanmean(b)
Dabei passiert aber nichts. Ich bekomme aber auch keine Fehlermeldung. Kann ich auf diese Weise überhaupt den Inhalt der Datensätze ansprechen und verwenden oder habe ich quasi duch glob.glob nur eine Auflistung meiner vorhandenen Daten erzeugt?

Ich danke schonmal herzlich, falls jemand helfen kann!

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Samstag 27. Juni 2015, 12:23
von BlackJack
@tine_beginner: Das Du keine Fehlermeldung bekommst kann nicht sein:

Code: Alles auswählen

In [1]: open(['a', 'b'])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-9a8631965ac0> in <module>()
----> 1 open(['a', 'b'])

TypeError: coercing to Unicode: need string or buffer, list found
`open()` mag als erstes Argument offenbar keine Liste. Was klar sein sollte wenn man sich die Dokumentation zu `open()` und Dateiobjekten durchliest und die entsprechenden Abschnitte im Python-Tutorial in der Python-Dokumentation durchgearbeitet hat.

Was `glob.glob()` für einen Rückgabewert hat (Typ/Wert) kannst Du doch ganz einfach überprüfen in dem Du Dir Typ und Wert von `alle` ausgeben lässt. Für ersteres gibt es die `type()`-Funktion.

Ich denke Du musst einfach erst einmal ein bisschen Zeit in Python-Grundlagen investieren. Ich würde mal sagen Funktionen selber schreiben und Generatorfunktionen und -ausdrücke kann man hier sehr gut gebrauchen. Und die Werkzeuge aus dem `itertools`-Modul sollten auch zum Grundwissen gehören.

Damit könntest Du Dir dann eine Funktion schreiben welche die Zeilen von allen Dateien deren Name als Liste übergeben wurde abzüglich der jeweils ersten neun Zeilen, nacheinander liefert. Damit kann man dann die `numpy.genfromtxt()` füttern um alle Dateien in ein grosses Array einzulesen.

Dabei könnte es natürlich passieren das die Datenmenge zu gross ist. Dann könnte man die Werte für die jeweiligen Einzeldateien berechnen und in einem Array speichern und dann zum Schluss diese aggregierten Werte noch einmal verrechnen.

Re: Konvertierung von Dezimaltrennzeichen

Verfasst: Samstag 27. Juni 2015, 13:30
von tine_beginner
@BlackJack: danke für deine Anmerkungen! Klingt erstmal deprimierend aber das ist auf jeden Fall schon mal was. Da es wirklich sehr viele Daten sind, werde ich denke ich versuchen, die Werte der einzelnen Dateien jeweils zu berechnen und dann mit einander zu verrechnen.

Das ganze klingt so simpel, aber naja.

D.h. es wäre in etwa sowas:

Code: Alles auswählen

import numpy as np
import glob
import matplotlib as plt

# alle Daten im Datensatz ansprechen
alle = glob.glob('*.csv')

for f in alle:
    with open(f) as data:
        b = np.genfromtxt((line.replace(',', '.') for line in data), skip_header=9, delimiter=";")
    
    print b.shape

    print np.nanmax(b),np.nanmin(b),np.nanstd(b),np.nanvar(b),np.nanmean(b)
Damit bekomme ich alle max, min, usw. Werte :) (Glücksgefühl). Diese könnte ich dann ja einfach wie Du schriebst in einem Array speichern und mir ein Gesamtergebnis ausgeben lassen. Wahnsinn! :D Ich bedanke mich nochmal! Ich versuche mal weiter und würde mich nochmal melden.