Graph plotten und Achse anpassen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Benutzeravatar
Ronsen90
User
Beiträge: 19
Registriert: Montag 22. Juni 2015, 10:46
Wohnort: Leipzig und Neustrelitz

Hallo,

ich habe schon wieder ein neues, ähnliches Problem wie im letzten Thread. Ich will einen Graphen plotten, habe aber ein Problem mit der x-Achse. Hier erst mal der Code:

Code: Alles auswählen

from pylab import *
from matplotlib import pyplot

xList = []
y1List = []
Dateiname = raw_input("Bitte das Verzeichnis eingeben: ") 
Datei = open(Dateiname) 
Counter = 0
Array = []
for line in Datei: 
    Counter = Counter + 1
    if Counter < 5:
        line = str(line)
    else:
        parts = line.split(",")
        y1List.append(float(parts[2]))
z1 = plot(y1List)
pyplot.ylabel("Strahlungsintensitaet")
pyplot.xlabel("Zeit")
pyplot.xticks(rotation ='vertical')
show(z1)
Die Ausgangsdateien sind txt-Files mit extrem vielen Zeilen (für jede Zehntelsekunde eine Zeile, ein File umfasst einen ganzen Tag, also 864000 Zeilen. Hier ein Ausschnitt:
"TOA5","CR1000","CR1000","E5930","CR1000.Std.25","CPU:RadMes_Melpitz.CR1","19011","Radiation"
"TIMESTAMP","RECORD","Dir_Wm2","PP1_Wm2","PP2_Wm2","TP1_Wm2","TP2_Wm2","PGE_Wm2"
"TS","RN","W/m2","W/m2","W/m2","W/m2","W/m2","W/m2"
"","","Smp","Smp","Smp","Smp","Smp","Smp"
"2015-05-06 11:33:20.3",355693953,643.4,370.6,902,362.6,884,341.5
"2015-05-06 11:33:20.4",355693954,644.7,370.6,903,362.2,884,341.6
"2015-05-06 11:33:20.5",355693955,646.1,370.6,904,362.6,885,341.7
"2015-05-06 11:33:20.6",355693956,646.5,370.6,904,362.2,886,341.2
"2015-05-06 11:33:20.7",355693957,647.4,370.6,905,362.2,887,341.5
"2015-05-06 11:33:20.8",355693958,647.9,370.6,906,362.2,888,341.5
"2015-05-06 11:33:20.9",355693959,648.8,370.6,907,362.2,888,341.8
"2015-05-06 11:33:21",355693960,651,370.6,908,362.2,889,341.3
"2015-05-06 11:33:21.1",355693961,651.9,370.6,909,362.2,890,341.7
Mein obiger Code ignoriert nun die ersten vier Zeilen (Spaltentitel) und trennt die nachfolgenden Zeilen anhand der Kommas. parts[2] bezieht sich auf die dritte Spalte. Die Diagramme, die dargestellt werden, zeigen auf der x-Achse nun die Zeilennummer an. Im Optimalfall sollte aber das Datum angezeigt werden. Wenn ich xList.append(float(parts[0])) hinzufüge und die y-Werte von x abhängig darstellen will, kommt ein Error, weil sich x nicht in eine float umwandeln lässt. Wenn ich xList.append(str(parts[0])) schreibe, kommt derselbe Fehler.

Also ich möchte mein Programm so anpassen, dass auf der x-Achse entweder das Datum steht (als String) oder dass auf der x-Achse gar nichts steht, das wäre die Notlösung, die auch in Ordnung wäre. Aber es sollten keine Zeilennummern dastehen. Vielleicht hat ja jemand von euch eine Idee?
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Du kannst die 1.Spalte in datetime Objekte umwandeln und aus diesen dann ein Numpy-Array machen:
http://stackoverflow.com/questions/1907 ... -in-python

oder Du machst das ganze Einlesen der Datei mit Pandas. Pandas macht das Plotten und Analysieren von Zeitreihen mit Matplotlib komfortabler.
http://pandas.pydata.org/pandas-docs/st ... n.html#min
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Ronsen90
User
Beiträge: 19
Registriert: Montag 22. Juni 2015, 10:46
Wohnort: Leipzig und Neustrelitz

Hallo MagBen,

ich habe mich an dem ersten Trick versucht, scheitere aber an der korrekten Umsetzung...

Code: Alles auswählen

from pylab import *
from matplotlib import pyplot
import datetime
import numpy as np

xList = []
y1List = []
Dateiname = raw_input("Bitte das Verzeichnis eingeben: ") 
Datei = open(Dateiname) 
Counter = 0
Array = []
for line in Datei: 
    Counter = Counter + 1
    if Counter < 5:
        line = str(line)
    else:
        parts = line.split(",")
        xList = np.array([datetime.datetime(2015,5,15,i,0) for i in range(24)])
        y1List = y1List.append(float(parts[2],size = xList.shape)) # an dieser Zeile scheitert es
z1 = plot(xList, y1List)
pyplot.ylabel("Strahlungsintensitaet")
pyplot.xlabel("Zeit")
pyplot.xticks(rotation ='vertical')
show(z1)
Weißt du auch, wie ich es hinbekomme, die Größe von y an meine x-Liste anzupassen? Der Fehler, der hier angezeigt wird, ist, dass float nur ein Argument einliest. In dem Beispiellink wird ja mit np.random.randint gearbeitet, wo man Shape noch angeben kann. Geht das auch ohne Zufallswerte und stattdessen mit meinen Daten?
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Zeile 5:

Code: Alles auswählen

from datetime import datetime
Zeile 18-19:

Code: Alles auswählen

        xList.append(datetime.strptime(parts[0], "%Y-%m-%d %H:%M:%S.%f"))
        y1List.append(float(parts[2]))
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Ronsen90
User
Beiträge: 19
Registriert: Montag 22. Juni 2015, 10:46
Wohnort: Leipzig und Neustrelitz

Danke dir, wir nähern uns dem Ziel. Jetzt kommt allerdings der Fehler:

ValueError: time data '"2015-05-06 00:00:00"' does not match format '%Y-%m-%d %H:%M:%S.%f'

Das hat doch bestimmt irgendwas mit dieser Zehntelsekunde zu tun. Time data scheint einen Doppelpunkt zu erwarten. Vielleicht muss der Punkt erst irgendwie mit einem Doppelpunkt ersetzt werden?
BlackJack

@Ronsen90: Lies doch einfach mal in der Dokumentation was dieser `strptime()`-Aufruf und insbesondere die ganzen Platzhalter bedeuten und dann kannst Du Dir überlegen wie Du diesen ”Sonderfall” mit Code behandelst.
Benutzeravatar
Ronsen90
User
Beiträge: 19
Registriert: Montag 22. Juni 2015, 10:46
Wohnort: Leipzig und Neustrelitz

Ja, ich werd's versuchen :|

Für mich ist die ganze Programmierung einfach noch ein Buch mit sieben Siegeln. Und die ganzen Hilfeseiten auf Englisch machen das nicht gerade einfacher. Ich bin ja schon froh, dass ich ungefähr verstanden habe, wie Schleifen funktionieren, aber speziellere Sachen muss man sich selbst zusammenreimen und da fehlt mir einfach völlig die Routine. Ich meine:

classmethod datetime.strptime(date_string, format)
"Return a datetime corresponding to date_string, parsed according to format. This is equivalent to datetime(*(time.strptime(date_string, format)[0:6])). ValueError is raised if the date_string and format can’t be parsed by time.strptime() or if it returns a value which isn’t a time tuple."

Das kann ich zehn Mal lesen und verstehe trotzdem kein Wort. Dann versuche ich, Begriffe wie parsen und Tupel zu verstehen, kann dann aber keinen Zusammenhang feststellen und geb es nach einer halben Stunde Googeln dann frustriert auf...

Edit: Ich kann mit diesen %-Angaben auch noch nicht so viel anfangen. Okay, %Y ist das Jahr, %m der Monat usw. Aber %f? Ich dachte, das ist so ein Stellvertreter für Floatzahlen. Aber hier scheint es mir um was anderes zu gehen,
BlackJack

@Ronsen90: Gerade wegen der Platzhalter hatte ich ja auf die Dokumentation verwiesen weil die da alle dokumentiert sind. Und das sind andere Bedeutungen als für den ``%``-Operator, deswegen ist '%f' keine Gleitkommazahl. Den letzten Satz von der Methodendokumentation hast Du ja weggelassen, weist auf den Abschnitt strftime() and strptime() Behavior hin wo die Formatangaben aufgelistet sind.

Was verstehst Du denn konkret nicht an der Dokumentation? Hauptsächlich sagt die doch aus das der Aufruf ``datetime(*(time.strptime(date_string, format)[0:6]))`` entspricht. Man müsste sich also zum besseren Verständis auch die Dokumentation von `time.strptime()` anschauen.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Das Format "%Y-%m-%d %H:%M:%S.%f" passt für Zeitstempel wie "2015-05-06 11:33:20.3" (Sekundenbruchteil),
aber nicht für Zeitstempel wie z.B. "2015-05-06 00:00:00" oder "2015-05-06 11:33:21" (volle Sekunde).
Ich weiß nicht ob man beides mit einem Format beschreiben kann. Wenn nicht, könntest Du die Länge des Zeitstempels untersuchen, bei einer Länge von 19 nimmst Du "%Y-%m-%d %H:%M:%S" ansonsten "%Y-%m-%d %H:%M:%S.%f" (und die nächste Fehlermeldung wird Dich dann auf weitere Zeitstempel Format Varianten hinweisen).
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Ronsen90
User
Beiträge: 19
Registriert: Montag 22. Juni 2015, 10:46
Wohnort: Leipzig und Neustrelitz

MagBen hat geschrieben:Das Format "%Y-%m-%d %H:%M:%S.%f" passt für Zeitstempel wie "2015-05-06 11:33:20.3" (Sekundenbruchteil),
aber nicht für Zeitstempel wie z.B. "2015-05-06 00:00:00" oder "2015-05-06 11:33:21" (volle Sekunde).
Ich weiß nicht ob man beides mit einem Format beschreiben kann. Wenn nicht, könntest Du die Länge des Zeitstempels untersuchen, bei einer Länge von 19 nimmst Du "%Y-%m-%d %H:%M:%S" ansonsten "%Y-%m-%d %H:%M:%S.%f" (und die nächste Fehlermeldung wird Dich dann auf weitere Zeitstempel Format Varianten hinweisen).
Achsooo... ja, das macht Sinn. In meiner Stringlänge herrscht keine Einheitlichkeit, deswegen funktioniert es nicht. Okay... nun gut, da habe ich zumindest erst mal einen Ansatz, mit dem ich herumprobieren kann. Vielen Dank!

Edit: Ja, erste Sahne. Es funktioniert :)

Hier mein geänderter Code:

Code: Alles auswählen

from pylab import *
from matplotlib import pyplot
from datetime import datetime

xList = []
y1List = []
Dateiname = raw_input("Bitte das Verzeichnis eingeben: ") 
Datei = open(Dateiname) 
Counter = 0
for line in Datei: 
    Counter = Counter + 1
    if Counter < 5:
        line = str(line)
    else:
        parts = line.split(",")
        if len(parts[0]) == 23:
            xList.append(datetime.strptime(parts[0], '"%Y-%m-%d %H:%M:%S.%f"'))
            y1List.append(float(parts[2]))
        elif len(parts[0])== 21:
            xList.append(datetime.strptime(parts[0], '"%Y-%m-%d %H:%M:%S"'))
            y1List.append(float(parts[2]))
z1 = plot(xList, y1List)
pyplot.ylabel("Strahlungsintensitaet")
pyplot.xlabel("Zeit")
pyplot.xticks(rotation ='vertical')
show(z1)
Antworten