2016-08-05 13 views
5

In der Definition der Funktion barh von matplotlib:Was ist die Einheit der Höhe variabel in "barh" von Matplotlib?

matplotlib.pyplot.barh(bottom, width, height=0.8, left=None, hold=None, **kwargs)

Der Standard "Höhe" ist 0,8, aber wenn ich zum Beispiel einiger Zahlen mit der Höhe der verschiedenen Abbildung Draw (30, 40, ..) und dpi = 100. Ich sehe die Höhe der Bar ist verändert. Es ist nicht behoben. Also frage ich mich, was ist die Einheit der Höhe in Barh und wie man es fixiert (nicht abhängig von der Höhe der Figur).

+0

Es ist erstaunlich, dass es keine einfache Möglichkeit gibt, eine feste Höhe einzustellen. –

Antwort

4

Ich werde dies in zwei Teile geteilt:

Ich frage mich, was die Einheit der Höhe in barh ist

(Offenbar haben die Menschen dieses since 2009 fragen ... also denke ich, Sie sind in guter Gesellschaft!)

Diese Frage ist der leichtere Teil - es ist ein Prozentsatz der Höhe, die der Leiste in der Abbildung zugewiesen ist. Der Standardwert height=0.8 bedeutet beispielsweise, dass die Höhe des Balkens 0.8 * (plot_height/n_bars) ist. Sie können dies sehen, indem Sie height=1.0 einstellen (oder sogar einen Wert> 1, die Balken überlappen sich). Wenn Sie wirklich sicher sein wollen, hier ist die source of axes.barh. Dies erfordert nur axes.bar - werfen Sie einen Blick auf these lines:

nbars = len(bottom) 
if len(left) == 1: 
    left *= nbars 
if len(height) == 1: 
    height *= nbars 

Und later on ...

args = zip(left, bottom, width, height, color, edgecolor, linewidth) 
for l, b, w, h, c, e, lw in args: 
    if h < 0: 
     b += h 
     h = abs(h) 
    if w < 0: 
     l += w 
     w = abs(w) 
    r = mpatches.Rectangle(
     xy=(l, b), width=w, height=h, 
     facecolor=c, 
     edgecolor=e, 
     linewidth=lw, 
     label='_nolegend_', 
     margins=margins 
     ) 
    r.update(kwargs) 
    r.get_path()._interpolation_steps = 100 
    #print r.get_label(), label, 'label' in kwargs 
    self.add_patch(r) 
    patches.append(r) 

So sehen Sie die Höhe von nbars skaliert wird, und wenn Sie das Rechteck zeichnen sind sie gestaffelt durch diese Höhe.

wie es

fixiert machen Das ist härter, werden Sie es manuell einstellen müssen. Die Balken auf dem Diagramm sind letztlich matplotlib.patches.Rectangle Objekte, die eine Breite und Höhe haben ... was auch ein Prozentsatz ist. Ich denke, die beste Lösung besteht darin, den entsprechenden Prozentsatz manuell zu berechnen.

Hier ist ein kurzes Beispiel, basierend aus einem barh demo:

import matplotlib.pyplot as plt 
plt.rcdefaults() 
import numpy as np 
import matplotlib.pyplot as plt 

# Example data 
people = ('Tom', 'Dick', 'Harry', 'Slim', 'Jim') 
y_pos = np.arange(len(people)) 
performance = 3 + 10 * np.random.rand(len(people)) 
error = np.random.rand(len(people)) 

plt.figure(figsize=(5,5), dpi=80) 
myplot = plt.barh(y_pos, performance, height=0.8, xerr=error, align='center', alpha=0.4) 
plt.yticks(y_pos, people) 
plt.xlabel('Performance') 
plt.title('How fast do you want to go today?') 

for obj in myplot: 
    # Let's say we want to set height of bars to always 5px.. 
    desired_h = 5 
    current_h = obj.get_height() 
    current_y = obj.get_y() 
    pixel_h = obj.get_verts()[2][1] - obj.get_verts()[0][1] 
    print("current position = ", current_y) 
    print("current pixel height = ", pixel_h) 

    # (A) Use ratio of pixels to height-units to calculate desired height 
    h = desired_h/(pixel_h/current_h) 
    obj.set_height(h) 
    pixel_h = obj.get_verts()[2][1] - obj.get_verts()[0][1] 
    print("now pixel height = ", pixel_h) 

    # (B) Move the rectangle so it still aligns with labels and error bars 
    y_diff = current_h - h # height is same units as y 
    new_y = current_y + y_diff/2 
    obj.set_y(new_y) 
    print("now position = ", obj.get_y()) 
plt.show() 

Teil A pixel_h/current_h berechnet eine Umwandlung zwischen den Pixeln und Höheneinheiten zu erhalten. Dann können wir desired_h (Pixel) durch dieses Verhältnis teilen, um desired_h in Höheneinheiten zu erhalten. Dadurch wird die Balkenbreite auf 5 px festgelegt, aber der untere Rand des Balkens bleibt an derselben Stelle, sodass er nicht mehr mit den Beschriftungen und Fehlerbalken ausgerichtet ist.

Teil B berechnet die neue y-Position. Da y und height in den gleichen Einheiten sind, können wir einfach die Hälfte des Höhenunterschieds hinzufügen (y_diff), um die neue Position zu erhalten. Dadurch bleibt der Balken in der ursprünglichen y-Position zentriert.

Beachten Sie, dass dies nur die anfängliche Größe festlegt. Wenn Sie beispielsweise die Größe des Diagramms ändern, skalieren die Balken weiterhin - Sie müssten dieses Ereignis überschreiben, um die Größe der Balken entsprechend anzupassen.

+0

Hi @whrrgarbi, wenn ich dein Programm starte, sehe ich: 'aktuelle Pixelhöhe = 42.67' und' jetzt Pixelhöhe = 5.0'. Aber wenn ich Ihre Formel verwende, um die Balkenhöhe zu berechnen, bekomme ich: 0.8 * (5 * 80)/5 = 64 verschieden von 42.67. Könntest du das noch einmal erklären? Die Grundstückshöhe ist: 5 * 80 Pixel richtig? – hminle

+0

@hminle Oh, guter Fang, ich bekomme das gleiche, aber ich habe nicht so viel Aufmerksamkeit geschenkt, da ich nur an der "Nach" -Messung interessiert war. Es sieht so aus, als ob ein Standard-Padding/Rand um die Balken herum vorhanden ist, wenn das "Rechteck" erstellt wird. Glücklicherweise basiert die Formel hier nur auf der endgültigen Höhe des Balkens, also endet sie wie erwartet 5px! – whrrgarbl

+0

Und noch eine Sache, wenn Sie auf die gewünschte Höhe wechseln, ist der Balken jetzt nicht horizontal ausgerichtet mit seinem y-Label. Und natürlich müssen wir auch y-Etiketten-Positionen berechnen. Aber wie können wir das tun? Da die sure_h Pixel ist, ist es nicht die gleiche Einheit mit Y-Label-Positionen. – hminle