it-swarm.com.de

Stellen Sie die Matplotlib-Farbleistengröße so ein, dass sie dem Diagramm entspricht

Ich kann nicht erreichen, dass der Farbbalken in imshow-Diagrammen wie diesem die gleiche Höhe wie im Diagramm hat, ohne Photoshop zu verwenden. Wie kriege ich die Höhen zusammen?Example of the colorbar size mismatch

124
Elliot

Sie können dies einfach mit einer matplotlib AxisDivider tun.

Das Beispiel von der verknüpften Seite funktioniert auch ohne die Verwendung von Unterplots:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np

plt.figure()
ax = plt.gca()
im = ax.imshow(np.arange(100).reshape((10,10)))

# create an axes on the right side of ax. The width of cax will be 5%
# of ax and the padding between cax and ax will be fixed at 0.05 inch.
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)

plt.colorbar(im, cax=cax)

enter image description here

157
bogatron

Diese Kombination (und Werte in der Nähe davon) scheint für mich "magisch" zu funktionieren, damit die Farbleiste auf das Diagramm skaliert bleibt, unabhängig von der Größe der Anzeige.

plt.colorbar(im,fraction=0.046, pad=0.04)

Es ist auch nicht erforderlich, die Achse zu teilen, wodurch der Plot aus dem Quadrat geraten kann.

173
skytaker

@bogatron hat bereits die von matplotlib docs vorgeschlagene Antwort gegeben, die die richtige Höhe ergibt, aber es tritt ein anderes Problem auf. Jetzt ändert sich die Breite des Farbbalkens (sowie der Abstand zwischen Farbbalken und Plot) mit der Breite des Plots. Mit anderen Worten, das Seitenverhältnis des Farbbalkens ist nicht mehr festgelegt.

Um sowohl die richtige Höhe als auch eines bestimmten Seitenverhältnisses zu erhalten, müssen Sie etwas tiefer in das mysteriöse axes_grid1 Modul.

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable, axes_size
import numpy as np

aspect = 20
pad_fraction = 0.5

ax = plt.gca()
im = ax.imshow(np.arange(200).reshape((20, 10)))
divider = make_axes_locatable(ax)
width = axes_size.AxesY(ax, aspect=1./aspect)
pad = axes_size.Fraction(pad_fraction, width)
cax = divider.append_axes("right", size=width, pad=pad)
plt.colorbar(im, cax=cax)

Beachten Sie, dass dies die Breite des Farbbalkens mit RT angibt. die Höhe des Plots (im Gegensatz zur Breite der Figur , wie es vorher war).

Der Abstand zwischen Farbbalken und Plot kann jetzt als Bruchteil der Breite des Farbbalkens angegeben werden, was meiner Meinung nach eine viel aussagekräftigere Zahl ist als ein Bruchteil der Bildbreite.

image plot with colorbar

AKTUALISIEREN:

Ich habe ein IPython-Notizbuch zum Thema erstellt, in dem ich den obigen Code in eine leicht wiederverwendbare Funktion gepackt habe:

import matplotlib.pyplot as plt
from mpl_toolkits import axes_grid1

def add_colorbar(im, aspect=20, pad_fraction=0.5, **kwargs):
    """Add a vertical color bar to an image plot."""
    divider = axes_grid1.make_axes_locatable(im.axes)
    width = axes_grid1.axes_size.AxesY(im.axes, aspect=1./aspect)
    pad = axes_grid1.axes_size.Fraction(pad_fraction, width)
    current_ax = plt.gca()
    cax = divider.append_axes("right", size=width, pad=pad)
    plt.sca(current_ax)
    return im.axes.figure.colorbar(im, cax=cax, **kwargs)

Es kann so verwendet werden:

im = plt.imshow(np.arange(200).reshape((20, 10)))
add_colorbar(im)
24
Matthias

Wenn Sie colorbar erstellen, versuchen Sie, die Bruch- und/oder Verkleinerungsparameter zu verwenden.

Aus den Unterlagen:

fraktion 0,15; Bruchteil der Originalachsen, die für die Farbleiste verwendet werden sollen

schrumpfen 1,0; Bruchteil, um den der Farbbalken verkleinert werden soll

8
Steve Barnes

Alle oben genannten Lösungen sind gut, aber ich mag @ Steve's und @ bejota's am besten, da sie keine ausgefallenen Anrufe beinhalten und universell sind.

Mit universal meine ich, dass das mit jeder Art von Achsen funktioniert, einschließlich GeoAxes. Beispielsweise haben Sie Achsen für das Mapping projiziert:

projection = cartopy.crs.UTM(zone='17N')
ax = plt.axes(projection=projection)
im = ax.imshow(np.arange(200).reshape((20, 10)))

ein Anruf an

cax = divider.append_axes("right", size=width, pad=pad)

wird fehlschlagen mit: KeyException: map_projection

Daher ist die einzige universelle Möglichkeit, mit der Größe von Farbbalken bei allen Arten von Achsen umzugehen, folgende:

ax.colorbar(im, fraction=0.046, pad=0.04)

Arbeiten Sie mit Brüchen von 0,035 bis 0,046, um die beste Größe zu erhalten. Die Werte für Bruch und Paddig müssen jedoch angepasst werden, um die beste Anpassung für Ihr Diagramm zu erzielen. Sie unterscheiden sich je nachdem, ob die Ausrichtung des Farbbalkens vertikal oder horizontal ist.

7
Bogdan

Ich schätze alle Antworten oben. Wie jedoch einige Antworten und Kommentare hervorhoben, ist das axes_grid1 Modul kann GeoAxes nicht adressieren, wohingegen das Anpassen von fraction, pad, shrink und anderen ähnlichen Parametern nicht unbedingt die sehr genaue Reihenfolge ergeben kann, was mich wirklich stört. Ich glaube, dass es eine bessere Lösung sein könnte, dem colorbar sein eigenes axes zu geben, um alle erwähnten Probleme anzugehen.

Code

import matplotlib.pyplot as plt
import numpy as np

fig=plt.figure()
ax = plt.gca()
im = ax.imshow(np.arange(100).reshape((10,10)))

# Create an axes for colorbar. The position of the axes is calculated based on the position of ax.
# You can change 0.01 to adjust the distance between the main image and the colorbar.
# You can change 0.02 to adjust the width of the colorbar.
# This practice is universal for both subplots and GeoAxes.

cax = fig.add_axes([ax.get_position().x1+0.01,ax.get_position().y0,0.02,ax.get_position().height])
plt.colorbar(im, cax=cax)

Ergebnis

enter image description here

3
Fei Yao