2015-02-15 6 views
5

Ich mache Standard Matplotlib Boxplots mit dem Befehl plt.boxplot(). My Codezeile, die die boxplot erstellt ist:Matplotlib Boxplot zeige nur max und min Flyer

bp = plt.boxplot(data, whis=[5, 95], showfliers=True) 

Weil meine Daten eine große Verbreitung hat, bin ich eine Menge von Flyern außerhalb des Bereichs der Whisker zu bekommen. Um eine sauberere Publikationsqualität zu erhalten, möchte ich nur einzelne Flyer maximal anzeigen. und bei der min. Werte der Daten, anstelle von allen Fliegern. Ist das möglich? Ich sehe keine integrierten Optionen in der Dokumentation, um dies zu tun.

(Ich kann die Reichweite der Whiskers auf max/min einstellen, aber das ist nicht was ich will. Ich möchte die Whiskers auf der 5. und 95. Perzentile halten).

Unten ist die Figur, an der ich arbeite. Beachten Sie die Dichte der Flyer. Boxplots

+0

Ist das nicht Dichte von Flyern wichtige Informationen? – tacaswell

+0

Ja, ist definitiv. Hängt davon ab, was Sie zu zeigen versuchen, nehme ich an. Aber du machst einen guten Punkt. – PJW

Antwort

3

plt.boxplot() gibt ein Wörterbuch, wo der Schlüssel fliers die oberen und unteren Flyern als Line2D Objekte enthält. Sie können sie manipulieren, wie dies vor Plotten:

Nur auf matplotlib> = 1.4.0

bp = plt.boxplot(data, whis=[5, 95], showfliers=True) 

# Get a list of Line2D objects, representing a single line from the 
# minimum to the maximum flier points. 
fliers = bp['fliers'] 

# Iterate over it! 
for fly in fliers: 
    fdata = fly.get_data() 
    fly.set_data([fdata[0][0],fdata[0][-1]],[fdata[1][0],fdata[1][-1]]) 

Bei älteren Versionen

Wenn Sie eine ältere Version von matplotlib sind, die Flieger für jeden Boxplot werden durch zwei Zeilen dargestellt, nicht eins. Somit würde die Schleife wie folgt aussehen:

import numpy as np 
for i in range(len(fliers)): 
    fdata = fliers[i].get_data() 
    # Get the index of the maximum y in data if 
    # i is 0 or even, else get index of minimum y. 
    if i%2 == 0: 
     id = np.where(fdata[1] == fdata[1].max())[0][0] 
    else: 
     id = np.where(fdata[1] == fdata[1].min())[0][0] 
    fliers[i].set_data([fdata[0][id], fdata[1][id]]) 

Beachten Sie auch, dass das showfliers Argument nicht in matplotlib < 1.4x existiert und das whisk Argument akzeptiert keine Listen.

Natürlich (für einfache Anwendungen) konnte man die boxplot ohne Flieger plotten und die maximalen und minimalen Punkte auf dem Grundstück hinzu:

bp = plt.boxplot(data, whis=[5, 95], showfliers=False) 
sc = plt.scatter([1, 1], [data.min(), data.max()]) 

wo [1, 1] die x-Position der Punkte ist.

+0

Ihre erste Lösung zeichnet alle Max Flyer gut, aber nicht die min. Wenn ich in min für max in den Code sub, dann nur die mins plot. Vielleicht vermisse ich etwas, aber wie bekomme ich sowohl das Maximum als auch das Min zum Plotten? Die zweite vorgeschlagene Lösung funktioniert nicht .... zeichnet einige Punkte unter den Boxen, aber sie sind nicht die Minuten. Und die dritte vorgeschlagene Lösung wird für mich nicht funktionieren, da "Daten" eigentlich eine Liste vieler Pandas-Datenframes sind (die mehrere Boxplots wie in der veröffentlichten Figur produzieren). Danke für Ihre Antwort, ich denke, es ist sehr nahe! – PJW

+0

Sorry, war gestern ein bisschen zu spät. Ich habe es oben behoben. Hoffe, es ist einigermaßen klar und einfach zu folgen. Habe auch den zweiten Vorschlag rausgenommen. – Geotob

+0

Nun, die min und max abwechselnd, so dass Box 1 zeigt nur die max, Box 2 zeigt nur die min, Box 3 zeigt nur die max, etc ...... ?? Siehe die oben hinzugefügte Abbildung. – PJW

1
fliers = bp['fliers'] 
for i in range(len(fliers)): # iterate through the Line2D objects for the fliers for each boxplot 
    box = fliers[i] # this accesses the x and y vectors for the fliers for each box 
    box.set_data([[box.get_xdata()[0],box.get_xdata()[0]],[np.min(box.get_ydata()),‌​np.max(box.get_ydata())]]) 
    # note that you can use any two values from the xdata vector 

Figur ergibt, zeigt nur max und min Flyern: enter image description here