Plotten mit Python

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
Benutzeravatar
frixhax
User
Beiträge: 39
Registriert: Donnerstag 21. April 2011, 14:06

Donnerstag 21. April 2011, 14:18

Hallo zusammen!
Ich möchte aus Python zwei Listen gegeneinander plotten und verwende dazu matplotlib.pyplot. Dabei möchte ich, dass pyplot zur Achsenbeschriftung KEINE wissenschaftliche Notation verwendet, sondern die Werte so an die Ticks schreibt, wie sie sind.
Die x-Liste enthält Daten im Format yyyymmdd (das soll auch so), wichtig ist hier nur, dass es quasi große Zahlen sind. Die y-Liste enthält ebenfalls große Werte in der Größenordnung von 10.000.
Das Problem ist nun, dass die Labels der Y-Achse richtig angezeigt werden, pyplot die Labels der x-Werte jedoch in wissenschaftliche Schreibweise uwandelt. Das bringt mir natürlich in diesem Falle überhaupt nichts, ich will meine Daten da stehen haben! ;)
Ich habe schon wild gegoogelt, finde dazu einige Tipps unter Verwendung von ticker.ScalarFormatter, allerdings funktioniert das alles nicht.
Das, was ich ganz simpel habe ist:

Code: Alles auswählen

import mathplotlib.pyplot as plt
value_list = [10000, 9000, 11000, 9000, 12000, 10000]
date = [20110104, 20110105, 20110106, 20110107, 20110108, 20110109]
plt.figure(1)
plt.plot(date, value_list, 'r-')
plt.xlabel('date')
plt.ylabel('flux')
plt.savefig('flux.png')
Dabei macht es auch keinen Unterschied, ob ich die Einträge von date in Strings umwandle oder nicht.
Das hatte ich jetzt versuchsweise umgeschrieben zu:

Code: Alles auswählen

import mathplotlib.pyplot as plt
value_list = [10000, 9000, 11000, 9000, 12000, 10000]
date = [20110104, 20110105, 20110106, 20110107, 20110108, 20110109]
plt.figure(1)
ax = plt.subplot(111)
plt.plot(date, value_list, 'r-')
formx = ticker.ScalarFormatter()
formx.set_scientific(False)
ax.xaxis.set_major_formatter(formx)
plt.xlabel('date')
plt.ylabel('flux')
plt.savefig('flux.png')
Aber ohne Erfolg, es sieht immer noch genauso aus wie vorher.
Das kann doch nicht so schwer sein, pyplot zu sagen, dass er die Finger von den Werten lassen soll, oder?
Bin für jegliche Hilfe dankbar :)
BlackJack

Donnerstag 21. April 2011, 14:58

@mohack: Der Plot wird erstellt wenn Du `plot()` aufrufst. Vielleicht macht es ja Sinn die Einstellungen an der Darstellung *vorher* zu machen.
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Donnerstag 21. April 2011, 17:11

@mohack: Bekommst Du das gewünschte Ergebnis, wenn du datetime.date()-Objecte verwendest?
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Donnerstag 21. April 2011, 17:12

@mohack: Warum "ScalarFormatter" nicht funktioniert, kann ich mir im Moment auch nicht erklären. Es gibt da noch "OldScalarFormatter", das bei mir das gewünschte Ergebnis liefert.

Ich würde dir alternativ vorschlagen mit DateTime Objekten zu arbeiten:

Code: Alles auswählen

from datetime import datetime as DateTime
import matplotlib.pyplot as plt

values = [10000, 9000, 11000, 9000, 12000, 10000]
dates = [20110104, 20110105, 20110106, 20110107, 20110108, 20110109]
dates = [DateTime.strptime(str(d), '%Y%m%d') for d in dates]

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(dates, values)
ax.set_xticklabels([d.strftime('%d.%m.%Y') for d in dates])

plt.show()
Edit: b.esser-wisser war ein bisschen schneller.
Edit2: Muss natürlich "ax.plot(dates, values)" heißen. Zuvor stand dort "ax.plot(datetimes, values)".
Zuletzt geändert von gkuhl am Freitag 22. April 2011, 04:24, insgesamt 1-mal geändert.
Benutzeravatar
frixhax
User
Beiträge: 39
Registriert: Donnerstag 21. April 2011, 14:06

Donnerstag 21. April 2011, 22:10

@BlackJack: Danke, aber das bewirkt lediglich, dass andere Anweisungen, wie labels oder limits, auch ignoriert werden.

@b.esser-wisser, gkuhl: Danke, das funktioniert so halb. Wenn ich das so mache, bekomme ich zwar eine hübsche Achsenbeschriftung, die aber nicht mehr mit den Messwerten übereinstimmt. Es gibt in meiner Liste nicht für alle Tage Werte, zwischendurch fehlen welche. Jetzt nummeriert er die Achse aber einfach in 1-Tages-Schritten durch. In der neuen dates Variable stimmen die Werte noch, die habe ich mir ausgeben lassen. Die Tage, die in der originalen dates-Liste fehlen, sind auch nicht in der neuen dates-Liste. Auch die Variable d legt er dann richtig an, die geht vom 10.9. bis 25.9., wie es sein soll. Nur die Achsenbeschriftung im Plot reicht nur vom 10.9. bis 16.9. und der erste y-Wert wird nicht für den 10.9. sondern für den 11.9. geplottet. Außerdem quetscht er alle Werte in den Plot, aber da auf der x-Achse zu wenig Tage sind, ordnet er nicht einen Wert pro Tag zu sondern dazwischen auch noch welche. Versteh ich alles überhaupt nicht... :K
UND: Ich würde das gerne verallgemeinern, da ich manchmal auch andere große Zahlenwerte (Anzahlen oder auch das Modifizierte Julianische Datum [Anzahl der Tage seit dem 17. November 1858]) auf der Achse haben. Gibt es keinen einfachen Weg, pyplot zu sagen "nimmt die Werte, wie sie in der Liste stehen, und fummel nicht dran rum sondern schreib sie mir genau so an die Achse"? Wie macht man das denn sonst mit großen Zahlenwerten? Wissenschaftliche Schreibweise, welche dafür ja bei pyplot Standard ist, macht ja nicht immer Sinn...
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Freitag 22. April 2011, 04:39

Verwende am besten "matplotlib.dates.DateFormatter". Damit werden die Beschriftung nicht überschrieben, wie in meiner ersten Variante, sondern richtig formatiert. Dann soltte die Probleme nicht mehr auftauchen. Ansonsten musst du mal etwas Code zeigen.

Hast du "OldScalarFormatter" schonmal ausprobiert?
Antworten