Python und matplotlib

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.
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Hallo zusammen,

ich habe ein Problem mit der matplotlib und hoffe, ihr könnt mir helfen.
Ich habe eine Datenbank, mache eine Abfrage und möchte das Ergebnis dieser Abfrage als Balkendiagramm mit Hilfe von matplotlib ausgeben.

Mein Plot sieht momentan so aus, dass ich eine x-Achse und zwei y-Achsen habe in etwa so:
http://www.mrunix.de/forums/attachment. ... 1281365569
Da ich bei der ersten Einheit der x-Achse zwei Balken habe und nicht nur einen, schreibt er die Bezeichnung der zweiten Einheit der x-Achse zum zweiten Balken, der aber noch zur erstenEinheit gehört. Ich hoffe, ihr versteht was ich meine.

Hier mein bisheriger Code:

Code: Alles auswählen

import sqlite3
import matplotlib.pyplot as plt
import numpy as np

connection = sqlite3.connect("MeineDatenbank.db")
cursor = connection.cursor()
cursor.execute("SELECT * FROM MeineTabelle")
ThisTable = cursor.fetchall()
Datum = []
Zeit = []
Distanz =[]
for entry in ThisTable:
    Datum.append(runtime[0])
    Zeit.append(runtime[1]/3600)
    Distanz.append(runtime[2]/1000)
print ThisTable

fig = plt.figure()
ax1 = fig.add_subplot(111)
N = len(Datum)
ind = np.arange(N)
width = 0.35
ax1.bar(ind, Zeit, width, color='orange', align='edge')
ax1.set_ylabel('Time', color='black')
ax1.set_xlabel('YYYY/MM', color='black')
ax1.set_xticks(ind + width)
ax1.set_xticklabels(Datum)

ax2 = ax1.twinx()
M = max(Distanz)
ind2 = np.arange(M)
ax2.set_xticklabels(Datum)

ax2.bar(ind, Distanz, width, color='black', align='center')
ax2.set_ylabel('Distanz', color='black')

plt.show()
Hat jemand eine Idee, wie man die Skalierung ändern kann?

Gruß Isa
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Hat denn echt keiner eine Idee oder ist unklar, was mein Problem ist?

Gruß Isa
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

maria_dolores hat geschrieben:Hat denn echt keiner eine Idee oder ist unklar, was mein Problem ist?
Mir ist es tatsächlich unklar. Male doch mal eine Skizze, was Du willst im Vgl zu dem, was Du bekommst und stelle die online.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Hallo,

also der erste Anhang ist der Plot wie es aussehen soll und der zweite wie es ist. Man achte bitte vor allem auf die x-Achse.
Ich hoffe, ihr versteht dann mein Problem. Ich habe die Farben vertauscht.. .

So soll es aussehen:
Bild

So sieht es aus:
Bild

Gruß Isa
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also Dein Quellcode kann doch gar nicht laufen! Der Name runtime wird doch gar nicht initialisiert!?!

Also nach Betrachtung dieses Beispiels hängt sich doch sicherlich alles an den Einträgen von "Datum" auf. Stehen da denn überhaupt drei drin?

Zudem finde ich immer nur xticks und nicht set_xticks. Zumindest in dem Beispiel und bei einem kurzen Überfliegen der Doku. Zudem beziehen die sich nicht auf das subplot-Objekt dabei.

Ansonsten poste einfach mal ein minimales, lauffähigs Beispiel! (Sprich, lass den ganzen Datenbank-Kram weg und definiere eine statische Datenstruktur - die auszutauschen ist dann ja trivial!)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Ok, mache ich. Sorry, dass ich es so umständlich mache..

Code: Alles auswählen

import matplotlib.pyplot as plt
import numpy as np

N = 3
M = 700
Date = ('2010/06', '2010/07', '2010/08')
Time = (4,5,2)
KM = (500, 690, 300)

fig = plt.figure()
ax1 = fig.add_subplot(111)
ind = np.arange(N)
width = 0.35
ax1.bar(ind, Time, width, color='orange', align='center', edgecolor='black')
ax1.set_ylabel('Time', color='black')
ax1.set_xlabel('YYYY/MM', color='black')
ax1.set_xticks(ind + width)
ax1.set_xticklabels(Date)

ax2 = ax1.twinx()
ind2 = np.arange(M)
ax2.set_xticklabels(Date)

ax2.bar(ind, KM, width, color='black', align='edge', edgecolor='orange' )
ax2.set_ylabel('KM', color='black')


plt.show()
Hier taucht dann das Problem wieder auf, dass die Einheiten der x-Achse nicht zu den zugehörigen Balken passen.

Habt ihr eine Idee, wie man das ändern kann?

Gruß Isa
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

ersetze

Code: Alles auswählen

ax1.set_xticks(ind + width)
ax1.set_xticklabels(Date)
durch

Code: Alles auswählen

plt.xticks(ind + width, Date)
dann hast du die Labels einmal fast richtig.

Dann entfernst du das align und fügst beim 2. bar() ein + width ein:

Code: Alles auswählen

import matplotlib.pyplot as plt
import numpy as np

N = 3
M = 700
Date = ('2010/06', '2010/07', '2010/08')
Time = (4,5,2)
KM = (500, 690, 300)

fig = plt.figure()
ax1 = fig.add_subplot(111)
ind = np.arange(N)
width = 0.35
ax1.bar(ind, Time, width, color='orange', edgecolor='black')
ax1.set_ylabel('Time', color='black')
ax1.set_xlabel('YYYY/MM', color='black')

ax2 = ax1.twinx()
ind2 = np.arange(M)
ax2.set_xticklabels(Date)

ax2.bar(ind + width, KM, width, color='black', edgecolor='orange' )
ax2.set_ylabel('KM', color='black')

plt.xticks(ind + width, Date)

plt.show()
und fertig ist das Skript (man kann noch ein paar Sachen vereinfachen und mMn besser anordnen).
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Hallo,

danke. Hat super funktioniert. Ich bin Neuling bei Python - was heisst mMn?

Gruß
Isa
Liffi
User
Beiträge: 153
Registriert: Montag 1. Januar 2007, 17:23

maria_dolores hat geschrieben:was heisst mMn?
"meiner Meinung nach"
Entspricht dem englischen imo (in my opinion), falls du mal darauf stossen solltest.
3ff
User
Beiträge: 191
Registriert: Dienstag 22. Dezember 2009, 12:54
Wohnort: Odenwald Sued-Hessen

@DaMutz
gut gemacht!
Fuer mich hat sich wieder 1 neue Pythonwelt aufgetan.
Ich werd demnaechst mit Latex arbeiten muessen (nicht mit diesem Lappy) und bin erstaunt, welche Plots man mit matplotlib alles erstellen kann.
Die Plots lassen sich in tkinter intergrieren und auch als PNG-Files abspeichern.
Ich war heute wieder bingen und dabei bin ich auf 1 interessante Fundstelle, was matplotlib angeht, gestossen.
matplotlib.sourceforge.net/examples/
Da hat es sogar 1 Beispiel zu pyqt4 gegeben. Also kann ich auch in pyqt4 plots aus matplotlib einbinden. In dem Beispiel war sogar 1 Animation der Cos-Funktion da, wo 1 Timerinterrupt genutzt wird, um den Canvas ¨äufzufrischen¨
Guude!
Fritz :lol:
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Ich habe da nochmal eine kleine Frage. Wenn ich für jede Einheit der x-Achse eine ganze Menge Balken haben möchte, kann ich das dann auch mit bar machen?

Gemeint ist es in etwa so:
Bild

Ich kann ja bei bar und align nur 'edge' oder 'center' auswählen. Wenn ich aber mehr als zwei Balken in einer Einheit der x-Achse darstellen will, verdecken sich die einzelnen Balken teilweise, eben weil ich nur diese beiden Argumente habe.

Ich hatte schon mal an ein Histogramm gedacht mit histtype='bar' aber das war auch nicht so ganz das wahre.

Hat jemand eine Idee, wie man das machen könnte?

Gruß Isa
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

Habe die Lösung eben gefunden.

Man muss, wenn man zB einen dritten Balken pro Einheit haben möchte einfach

Code: Alles auswählen

ax3 = ax1.twinx()
rects3 = ax3.bar(ind + 2*width, ...)
schreiben und so weiter.

Jetzt sieht mein Plot in etwa so aus:
Bild

Allerdings werden auf der rechten y-Achse die Einträge überschrieben und sind teilweise gar nicht mehr lesbar. Gibt es dafür irgendeine Lösung?

Gruß Isa
BlackJack

@maria_dolores: Du darfst halt keine "dritte" X-Achse aufmachen. Wenn die Werte dort auch in KM sind, dann verwende halt die zweite X-Achse dafür. Du willst doch sicher für die weiteren Balken für alle die gleiche Skalierung haben, sonst wäre das ja sowieso etwas schwierig zu lesen/interpretieren.
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

@BlackJack Danke. Hat super geklappt. Ich habe jetzt versucht es so zu machen:

Code: Alles auswählen

import matplotlib.pyplot as plt
import numpy as np

N = 3
M = 700
Date = ('2010/06', '2010/07', '2010/08')
Time = (4,5,2)
KM = (500, 690, 300)
KM_15 = (20, 50, 10)
KM_35 = (40, 60, 25)
KM_70 = (100, 170, 89)

fig = plt.figure()
ax1 = fig.add_subplot(111)
ind = np.arange(N)
width = 0.07
ax1.bar(ind, Time, width, color='orange', edgecolor='black')
ax1.set_ylabel('Time', color='black')
ax1.set_xlabel('YYYY/MM', color='black')

ax2 = ax1.twinx()
ind2 = np.arange(M)
ax2.set_xticklabels(Date)

ax2.bar(ind + width, KM, width, color='black', edgecolor='orange' )
ax2.set_ylabel('KM', color='black')

ax3 = ax1.twinx()
ax2.bar(ind + 2*width, KM_15, width, color='red')

ax4 = ax1.twinx()
ax2.bar(ind + 3*width, KM_35, width, color='green')

ax5 = ax1.twinx()
ax2.bar(ind + 4*width, KM_70, width, color='blue')


plt.xticks(ind + width, Date)

plt.show()
Jetzt sind auf der rechten y-Achse nur noch die Skalierungen von 0 bis 700 KM.und von 0.0 bis 1.0 in 0.2er Schritten. Kann man die Skalierung von 0.0 bis 1.0 irgendwie weg kriegen?

Gruß Isa
BlackJack

@maria_dolores: Klar, Du must einfach nur die Achsen weglassen bei denen Du dann gar keine Werte plottest. Dann verschwindet auch die Beschriftung von deren Standardbereich von 0.0 bis 1.0. :-)
3ff
User
Beiträge: 191
Registriert: Dienstag 22. Dezember 2009, 12:54
Wohnort: Odenwald Sued-Hessen

Hallo Gemeinde,
irgendwie ist mein letzter Beitrag verschwunden.
Zu matplotlib gibts 1 gute Quelle:
matplotlib.sourceforge.net/examples/
besser ist folgendes:
locate matplotlib
dann kam bei meinem Ubuntu 9.1
/usr/share/doc/python-matplotlib-doc/examples/mplot3d/bars3d_demo.py

die Datei versteht der Python-Interpreter die Bibs sind schon alle auf Ubuntu angepasst.
----------------------------------------
Super, denn ich muss mit Latex und 1 Beamer Vortraege halten und da kam es mir sehr recht
Der Suchpfad wird bei Suse oder Mandrake bestimmt anders lauten.
Goode!
Fritz 8) 8)
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

@BlackJack: Kannst Du mir vielleicht per Code sagen wie und wo ich die Achsen weglassen soll.. hemhem.. :? Ich hab es zwar eben versucht, aber ich weiss nicht genau wo ich das dann machen muss.

Gruß Isa
MTroi
User
Beiträge: 2
Registriert: Mittwoch 11. August 2010, 11:48

Hallo!
Ich habe ein ähnliches Problem beim Zeichnen meines Graphen und hoffe auf eure Hilfe.

Erläuterung: Der Graph basiert aus Werten der "*-result.csv" (s- ganz unten) in der gemessene Werte für
Up- und Downstream eines DSL Modems drinstehen sowie Richtwerte die als Vorgabe für die verschiedene
Leitungslängen dienen.
Der Graph stellt nun die Richtwerte als gestrichelte und die gemessenen Werte als durchgezogene Linie dar,
wobei die linke y-Achse für die Upstream und die rechte y-Achse für den Downstream stehen und
über die x-Achse die Leitungslänge aufgetragen ist.

Das Problem:
Das zeichnen klappt auch, aber die Zuordnung von Y-Werten zur X-Achse ist völlig falsch.
Ich hoffe hier kann mir jemand eine Lösung finden oder zumindest das Problem genau benennen, ich selber
bin jetzt mit meinem Latein am Ende.

Code: Alles auswählen

#Import needed Modules
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import csv2rec
import matplotlib.font_manager
from pylab import *

filename = "test"

if __name__ == "__main__":
    
    print "Generating Graph"
    
    prop = matplotlib.font_manager.FontProperties(size=10) #Set Font Size
    
    data = csv2rec(filename + "-result.csv",delimiter=',') #Read csv File
    
    N = len(data['length_m']) #Get # of lengths
    Up_Exp = data['up_rate_expected_kbps'] #Read Data From Corresponding Columns
    Up_Meas = data['up_rate_measured_kbps']
    Down_Exp = data['ds_rate_expected_kbps']
    Down_Meas = data['ds_rate_measured_kbps']
    
    ind = np.arange(N)  # The X Locations
    
    fig = plt.figure() #Make Graph
    ax1 = fig.add_subplot(111)

    line1 = ax1.plot(ind, Up_Exp, color='b', ls='dashdot')
    line2 = ax1.plot(ind, Up_Meas, color='b')
    
    ax2 = ax1.twinx()
    line3 = ax2.plot(ind, Down_Exp, color='r', ls='dashdot')
    line4 = ax2.plot(ind, Down_Meas, color='r')
    
    for Up_Exp in ax1.get_yticklabels(): #Color for the US Values blue
	Up_Exp.set_color('b')
    
    for Down_Exp in ax2.get_yticklabels(): # Color for the DS Values red
	Down_Exp.set_color('r')
	    
    ax1.set_ylim(ymin=0) #Start with 0 
    ax2.set_ylim(ymin=0) #Start with 0
    #ax1.yaxis.grid(color='grey', linestyle='dashed')
    #ax2.yaxis.grid(color='grey', linestyle='dashed')
    ax1.xaxis.grid(color='gray', linestyle='dashed') #For better orientation
    ax1.set_ylabel('Upstream Rate (kbps)')
    ax2.set_ylabel('Downstream Rate (kbps)')
    ax1.set_xticklabels(data['length_m'])
    ax1.set_title('Up- and Downstream Values')
	
    ax2.legend( (line1[0], line2[0], line3[0], line4[0]), ('Up (mandatory)', 'Up (measured)', 'Down (mandatory)', 'Down (measured)'), prop=prop, loc=0 )

    result_graph = filename + '-graph.png'
    savefig(result_graph)
Das Resultat:
Bild

Mein test-result.csv:
Length (m),"UP Rate (Expected, kbps)","UP Rate (Measured, kbps)",Pass/Fail, UP Noise Margin (dB),"DS Rate (Expected, kbps)","DS Rate (Measured, kbps)",Pass/Fail,DS Noise Margin (dB)
150,10000,12468,PASS,5.6,44192,50380,PASS,5.6
300,9000,11464,PASS,5.7,40712,43388,PASS,5.7
750,7600,7896,PASS,6.1,27076,30240,PASS,6.1
1200,1328,1756,PASS,9.7,17328,23404,PASS,9.7
1800,748,0,FAIL,0.0,8380,0,FAIL,0.0
maria_dolores
User
Beiträge: 39
Registriert: Dienstag 10. August 2010, 12:38

@BlackJack: Ich weiss jetzt, was Du mit löschen der Axen, bei denen nichts geplottet wird gemeint hast.
Ich habe mein Problem soeben gelöst.
Ich musste aus meinem Code folgendes löschen:

Code: Alles auswählen

ax3 = ax1.twinx()
ax4 = ax1.twinx()
ax5 = ax1.twinx()
Dann stehen auf der rechten y-Achse nur noch die KM von 0 bis 700.

Wenn ich bei einen logscale einfügen möchte, der aber nicht beo 10, sondern bei 0.01 anfängt, wie mache ich denn sowas?

Hier mein jetziger Plot:

Bild

Bei der zweiten Einheit der x-Achse verschwindet ein Balken rein optisch, weil die Daten da so klein sind. Ich möchte meine rechte y-Skala so abändern, dass man diese 'verschwundenen' Balken wieder erkennen kann.

Ich hoffe, ihr versteht was ich meine.

Hat da jemand eine Hinweis oder eine Lösung für mich?

Gruß Isa
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

@Isa:
einen log-Plot kannst du von der Matplotlib Gallery abschreiben:
semilogy()
http://matplotlib.sourceforge.net/examp ... _demo.html
Wenn die Werte genug klein sind so werden auch 10^-2 (0.01) dargestellt, denke ich.

@MTroi:

es ist nicht sehr höflich einen bestehenden Thread zu übernehmen. Aber die Lösung ist relativ einfach:
ersetze

Code: Alles auswählen

ind = np.arange(N)  # The X Locations
durch

Code: Alles auswählen

ind = data['length_m']
und lösche

Code: Alles auswählen

ax1.set_xticklabels(data['length_m'])
Antworten