Matplotlib: Datei über absolut Pfad plotten

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
HrSumsemann
User
Beiträge: 28
Registriert: Donnerstag 19. Februar 2015, 17:32

Hallo allerseits,

ich habe ein kleines Problem:

Ich habe eine Liste mit Absolutpfaden von Textdateien. Nun würde ich gerne jede dieser Dateien, bzw. Absolutpfade mit matplotlib Plotten.
Könnt Ihr mir sagen wie ich das am besten anstelle?

Meine Daten liegen folgender Maßen in einer Textdatei vor:

data_gut c:\Users\testing\Desktop\Datenkurven\data_gut\21.txt
data_gut2 c:\Users\testing\Desktop\Datenkurven\data_gut2\22.txt
data_gut3 c:\Users\testing\Desktop\Datenkurven\data_gut3\23.tx

Diese habe ich über einen Splitbefehl so getrennt, dass ich einmal die Namen für die Legende und einmal die Absolutpfade entkoppelt habe:

Code: Alles auswählen

      
    fread =open(filename)
    for line in fread:
        fsplitname = line.split(' ', 1)[0]
        fsplitpath = line.split(' ', 1)[1]


Nun geht es darum, die Daten zu verarbeiten. So in der Art habe ich mir das vorgestellt, ist aber vermutlich völlig falsch:

Code: Alles auswählen

for fname in fsplitpath:
            data=np.loadtxt(fname, skiprows=3)
            print data
            X=data[:,0]
            Y=data[:,1]
            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(X,Y, linestyle = '-', label = fsplitname)
            plt.legend()
            plt.show()

Hoffe Ihr könnt mir helfen :)
BlackJack

@HrSumsemann: Grunsätzliches Vorgehen ist okay, die Beispielquelltexte sind natürlich nicht lauffähig und fehlerhaft, aber es macht vielleicht auch nicht so viel Sinn über Code zu reden der nicht ”echt” ist.

Die Namen sind nicht so gut. `fread` wäre für eine Lesefunktion passend aber nicht für ein Dateiobjekt. `fsplitname` und `fsplitpath` würde man eher `name` und `filename` oder `path` nennen. Was soll das `f` und das `split` in dem Namen? Für den leser ist doch wichtig was der Wert bedeutet, nicht woher der kommt und mit welchem Methodenaufruf der entstanden ist.

Das `split()` zweimal exakt gleich aufgerufen wird nur um dann *einen* Teil des Ergebnisses an einen Namen zu binden ist ineffizient. Man könnte auch ``name, filename = line.split(' ', 1)`` schreiben.

Falls die beiden Namen nicht *in* der Schleife verwendet werden, würde ich die Informationen an dieser Stelle auch nicht trennen, denn Name und Dateiname gehören ja zusammen, sollten dementsprechend auch gemeinsam in einer Datenstruktur gespeichert werden. Das fehlt da nämlich auch noch, dass Du Dir die Ergebnisse der einzelnen Zeilen irgendwo merkst, zum Beispiel in einer Liste, denn sonst ist an die beiden Namen am Ende ja nur das Ergebnis der letzten Zeile aus der Datei gebunden.

Beim zweiten Quelltext ist `fsplitpath` nicht der gleichnamige Wert aus dem ersten, denn im ersten ist das *eine* Zeichenkette, hier jetzt eine Liste (?) mit Zeichenketten. Solche Containerobjekte werden üblicherweise in der Mehrzahl benannt, ausgehend von der Bedeutung eines einzelnen Elements. Eine Liste von Dateinamen also beispielsweise `filenames` weil ein einzelnes Element `filename` heissen würde. Und das sollte man auch ausschreiben und nicht zu `fname` verkürzen.

Numpy's `loadtxt()`-Funktion kennt ein `unpack`-Argument das Du Dir vielleicht mal anschauen könntest.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

HrSumsemann hat geschrieben:Nun geht es darum, die Daten zu verarbeiten. So in der Art habe ich mir das vorgestellt, ist aber vermutlich völlig falsch:
Probier's doch aus, anstatt es Dir nur vorzustellen.

Hier ein paar Verbesserungsvorschläge:
Zeile 3: print data.shape Arrays können mitunter sehr groß werden.
Zeile 7 ist unnötig, add_subplot brauchst Du nicht, wenn Du lediglich einen subplot pro figure hast.
Zeile 8:
linestyle='-' ist der Default-Style, das muss nicht explizit gesetzt werden.
Wenn Du nur eine Kurve hast, dann würde ich die Legende eher in den Titel stecken
plt.title(fsplitname)
Zeile 10: plt.show() sollte nicht in der Schleife, sondern nach der Schleife aufgerufen werden. Sonst siehst Du alle Plot-Fenster nur nacheinander und nicht gleichzeitig.
Wenn fsplitname den absoluten Pfad enthält, dann ist das auch keine gute Legende, die Legende zieht sich ja quer über den ganzen Plot. Ich würde als Legende nur den Dateinamen ohne den ganzen Pfad nehmen.

Probier zum Vergleich mal das:

Code: Alles auswählen

plt.figure()
for fname in fsplitpath:
    data=np.loadtxt(fname, skiprows=3)
    print data.shape, fname
    x=data[:,0]
    y=data[:,1]
    plt.plot(x,y, label=fsplitname)
plt.legend()
plt.show()
a fool with a tool is still a fool, www.magben.de, YouTube
HrSumsemann
User
Beiträge: 28
Registriert: Donnerstag 19. Februar 2015, 17:32

Danke für Eure Tips, werde versuchen diese umzusetzen :)

@MagBen

Habe mich etwas blöd ausgedrückt, ich habe es versucht so auzuführen, erhalte jedoch folgende Fehlermeldung:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/markus/Druckkurven/folderplotting.py", line 191, in <module>
read_plottinglist()
File "/home/markus/Druckkurven/folderplotting.py", line 152, in read_plottinglist
data=np.loadtxt(fname, skiprows=3)
File "/usr/lib/python2.7/dist-packages/numpy/lib/npyio.py", line 734, in loadtxt
fh = iter(open(fname, 'U'))
IOError: [Errno 21] Is a directory: '/'



Ich bin davon ausgegangen, dass ggf. loadtxt solche Pfadangaben nicht verarbeiten kann, aber da ich ein blutiger Anfänger bin, dachte ich mir ich poste meinen Ansatz mal, bevor ich völlig in die flasche Richtung arbeite ;)


Ach wg. des Subplots: Ich hatte geplant (bin aber noch nicht soweit), erstmal jede Datei für sich zu plotten und anschließend alle Daten in ein Diagramm zu stecken. Daher schonmal das mit den Legendeneinträgen :)

Danke und Gruß
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Füge vor Zeile 152 in folderplotting.py folgende Debug-Ausgabe ein:
print fname
Die Fehlermeldung besagt, dass fname nicht der Pfad einer Datei, sondern eines Verzeichnisses ist, nämlich das Rootverzeichnis '/'.
a fool with a tool is still a fool, www.magben.de, YouTube
HrSumsemann
User
Beiträge: 28
Registriert: Donnerstag 19. Februar 2015, 17:32

So habe mal ein paar Print Befehle eingefügt.
Einmal:
print "|| DATEI", i, " ---", fsplitname, "~ PFAD: ", fsplitpath

direkt dadrunter der einzelne print fsplitpath

und nochmal in dem Matplotlibteil

Code: Alles auswählen

def read_plottinglist():
    i = 0
    fread =open(filename)
    for line in fread:
        fsplitname = line.split(' ', 1)[0]
        fsplitpath = line.split(' ', 1)[1]
        print "|| DATEI", i, " ---",  fsplitname, "~ PFAD: ", fsplitpath
        print fsplitpath

     #   MATPLOTLIB
        for fname in fsplitpath:
            print fname
            data=np.loadtxt(fname, skiprows=3)
            print data
            X=data[:,0]
            Y=data[:,1]
            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(X,Y, label = fsplitname)
            #plt.plot(X,Y,'o:', label = dirname)
            legend = plt.legend(prop={'size': 1}

            plt.legend()
            plt.show()
Als Ausgabe bekomme ich das:

Code: Alles auswählen

|| DATEI 1  --- data_gut2 ~ PFAD:  /home/markus/Druckkurven/data_gut2/22.txt

/home/markus/Druckkurven/data_gut2/22_pr_ang_f.txt

/
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/markus/Druckkurven/folderplotting.py", line 193, in <module>
    read_plottinglist()
  File "/home/markus/Druckkurven/folderplotting.py", line 154, in read_plottinglist
    data=np.loadtxt(fname, skiprows=3)
  File "/usr/lib/python2.7/dist-packages/numpy/lib/npyio.py", line 734, in loadtxt
    fh = iter(open(fname, 'U'))
IOError: [Errno 21] Is a directory: '/'
Die ersten beiden Prints funktionieren, nur der hinter:
# MATPLOTLIB
for fname in fsplitpath:
print fname

gibt das Verzeichnis aus.



Danke
BlackJack

@HrSumsemann: Naja es macht ja auch keinen Sinn über *einen* Pfadnamen zu iterieren — da bekommt man dann in `fname` die einzelnen Zeichen dieses Pfadnamens. `fsplitpath` ist doch schon das was Du als `fname` haben willst, was hast Du Dir bei der ``for``-Schleife denn gedacht was die bewirken soll?
HrSumsemann
User
Beiträge: 28
Registriert: Donnerstag 19. Februar 2015, 17:32

Also gedacht war, das für jeden Eintrag aus fsplitpath, also jeden der drei Absolutpfade der folgende Prozess durchgeführt wird und ein Plot erzeugt.
BlackJack

@HrSumsemann: `fsplitpath` ist nichts was drei Einträge hat sondern ist *eine* Zeichenkette mit *einem* Pfad. Und dieser Name wird für jede Iteration der äusseren Schleife an einen der (drei) Einträge aus der Textdatei gebunden. Da *noch* eine Schleife reinzubasteln macht keinen Sinn. Das müsstest Du doch aber auch Anhand der Ausgaben des Programms *sehen*.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Probier das mal

Code: Alles auswählen

def read_plottinglist():
    i = 0
    fread =open(filename)
    for line in fread:
        fsplitname = line.split(' ', 1)[0]
        fsplitpath = line.split(' ', 1)[1]
        print "|| DATEI", i, " ---",  fsplitname, "~ PFAD: ", fsplitpath
        print fsplitpath
        
        data=np.loadtxt(fsplitpath, skiprows=3)
        print data.shape
        X=data[:,0]
        Y=data[:,1]
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.plot(X,Y, label = fsplitname)
        plt.legend()
    plt.show()
a fool with a tool is still a fool, www.magben.de, YouTube
HrSumsemann
User
Beiträge: 28
Registriert: Donnerstag 19. Februar 2015, 17:32

@MagBen

habe deinen Quelltext mal probiert, erhalte jedoch folgende Meldung

Code: Alles auswählen

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/markus/Druckkurven/folderplotting.py", line 210, in <module>
    read_plottinglist()
  File "/home/markus/Druckkurven/folderplotting.py", line 182, in read_plottinglist
    data=np.loadtxt(fsplitpath, skiprows=3)
  File "/usr/lib/python2.7/dist-packages/numpy/lib/npyio.py", line 734, in loadtxt
    fh = iter(open(fname, 'U'))
IOError: [Errno 2] No such file or directory: '/home/markus/Druckkurven/data_gut2/22_pr_ang_f.txt\n'

An sich nimmt er den Pfad ja schonmal korrekt an, nur ist am Ende hier noch ein \n??


Danke für die Hilfe :)
BlackJack

@HrSumsemann: Das Zeilenendezeichen was am Ende jeder Zeile in Textdateien steht damit man sieht das die Zeile zuende ist. Musst Du halt entfernen, mit der `strip()`- oder `rstrip()`-Methode.
HrSumsemann
User
Beiträge: 28
Registriert: Donnerstag 19. Februar 2015, 17:32

Funktioniert mit dem Strip('\n')-Befehlt, besten Dank und schönes Wochenende ;)
HrSumsemann
User
Beiträge: 28
Registriert: Donnerstag 19. Februar 2015, 17:32

Eine Frage an der Stelle, wie schaffe ich es, die Diagramme nachdem sie als Einzelplots erzeugt wurden, nochmal in einem Diagramm anzuzeigen?

Danke :)
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Du müsstest alle Plots nochmal erzeugen, diesmal aber plt.figure() nicht in der Schleife aufrufen, sondern nur einmal vor der Schleife.
a fool with a tool is still a fool, www.magben.de, YouTube
HrSumsemann
User
Beiträge: 28
Registriert: Donnerstag 19. Februar 2015, 17:32

Alles klar, werde ich machen. Danke :) Ging von aus, dass ich die figures wieder in der Schleife erzeuge und nur das show() bzw. savefig aus der Schleife raus ziehen muss.
Antworten