Встановіть розмір кольорової панелі Matplotlib відповідно до графіка


161

Я не можу отримати кольорову панель на таких графіках, як ця, щоб вона була такою ж висотою, що й графіка, окрім використання Photoshop після факту. Як домогтися відповідності висотам?Приклад невідповідності розміру кольорової панелі


Ви пробували пропозиції від stackoverflow.com/questions/16702479 / ...
lmjohns3

@ imjohns3 Ніщо в цій публікації, здається, не робить нічого із кольорової смуги. Він залишається однакового розміру незалежно від того, що я встановив. Якщо я встановлю фракцію і зменшуватимуся, розмір графіка змінюватиметься, коли кольорова смужка залишатиметься однаковою, поки ми не повернемося до того, що я вже мав, тоді вони перестануть робити щось.
Елліот

Перевірте документи - matplotlib.org/api/colorbar_api.html - і використання fractionабо shrinkарг.
BoltzmannBrain

Відповіді:


194

Зробити це можна легко за допомогою matplotlib AxisDivider .

Приклад із пов’язаної сторінки також працює без використання субплотів:

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)

введіть тут опис зображення


1
Я не працюю всередині subplot, тому це не застосовується.
Елліот

Після довгих роздумів змусив його працювати. У вас багато проблем з взаємодією з subplot_adjust, вам потрібно телефонувати в потрібних місцях відносно один одного.
Елліот

11
Це трохи змінює розмір графіків. У мене в сітці 2х2 є 4, але хочу лише, щоб два праворуч мали смуги (масштаб застосовується за рядками). Однак це робить їх не однакового розміру. Я намагався просто не мати дзвінка в кольоровій смузі (з викликом дільника), але, звичайно, це залишає порожнє біле поле і цифри збоку. Як я можу зробити так, щоб вони мали послідовний розмір, не ставлячи бруски на них?
Елліот

@bogatron На жаль, це не працює з прогнозованими осями
Богдан

Якщо ви хочете додати заголовок за допомогою plt.title, він відображатиметься поміщеним праворуч. Чи є спосіб подолати це?
користувач2820579

224

Ця комбінація (і значення, близькі до цих), здається, "магічно" працює для мене, щоб кольорова смуга наблизилася до сюжету, незалежно від розміру екрана.

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

Він також не вимагає спільного використання осі, яка може дістати ділянку з квадрата.


4
Це може спрацювати в деяких випадках, але загалом це не так. Спробуйте, наприклад, побудувати щось подібне до оригінального запитання, яке має ширину вдвічі більше висоти.
Маттіас

Варіант дробу все ще працює у випадку, про який ви згадуєте, якщо масштабувати відповідно до висоти ділянки. (mpl v1.4.3)
skytaker

6
Це єдиний універсальний спосіб зробити це. Рішення з axex_grid1 не працюватимуть для проектованих осей, таких як GeoAxes.
Богдан

OMG це приголомшливо. Дуже дякую за рішення
2D_

3
У відповідь на коментар @Matthias Ви можете виправити випадок, коли зображення занадто широке, використовуючи цей трюк: im_ratio = data.shape[0]/data.shape[1] plt.colorbar(im,fraction=0.046*im_ratio, pad=0.04)де dataваше зображення.
eindzl

30

@bogatron вже дав відповідь, запропоновану документами matplotlib , що створює потрібну висоту, але це вводить іншу проблему. Тепер ширина кольорової смуги (а також простір між кольоровою смугою та сюжетом) змінюється з шириною сюжету. Іншими словами, співвідношення сторін кольорової панелі вже не фіксується.

Щоб отримати як потрібну висоту, так і задане співвідношення сторін, вам слід заглибитися трохи глибше в таємничий axes_grid1модуль.

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)

Зауважте, що це визначає ширину кольорової смуги wt висоти ділянки (на відміну від ширини фігури, як це було раніше).

Тепер інтервал між кольоровою смугою та графіком може бути визначений як частка ширини кольорової смуги, що є IMHO набагато більш значущим числом, ніж частка ширини фігури.

зображення сюжет з кольоровою панеллю

ОНОВЛЕННЯ:

Я створив зошит IPython з цієї теми , куди я спакував вищезазначений код у легко повторну функціональну функцію:

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)

Його можна використовувати так:

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

1
Це дійсно корисна маленька функція! Одне слово попередження полягає в тому, що воно не працює, коли потрібно додати кілька кольорових смуг, оскільки вони з’являються один на одного.
Девід Холл

22

Я ціную всі відповіді вище. Однак, як і деякі відповіді та коментарі вказали, axes_grid1модуль може не адреса GeoAxes, тоді як регулювання fraction, pad, shrinkта інші подібні параметри можуть не обов'язково дати дуже точний порядок, який дійсно турбує мене. Я вважаю, що дати colorbarвласне axesможе бути кращим рішенням для вирішення всіх згаданих питань.

Код

import matplotlib.pyplot as plt
import numpy as np

fig=plt.figure()
ax = plt.axes()
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) # Similar to fig.colorbar(im, cax = cax)

Результат

введіть тут опис зображення

Пізніше я знаходжу, що matplotlib.pyplot.colorbarофіційна документація також дає axможливість, це наявні осі, які забезпечать місце для кольорової панелі. Тому це корисно для декількох підсплавів, див. Нижче.

Код

fig, ax = plt.subplots(2,1,figsize=(12,8)) # Caution, figsize will also influence positions.
im1 = ax[0].imshow(np.arange(100).reshape((10,10)), vmin = -100, vmax =100)
im2 = ax[1].imshow(np.arange(-100,0).reshape((10,10)), vmin = -100, vmax =100)
fig.colorbar(im1, ax=ax)

Результат

введіть тут опис зображення

Знову ж таки, ви можете досягти подібних ефектів, вказавши cax, більш точний спосіб з моєї точки зору.

Код

fig, ax = plt.subplots(2,1,figsize=(12,8))
im1 = ax[0].imshow(np.arange(100).reshape((10,10)), vmin = -100, vmax =100)
im2 = ax[1].imshow(np.arange(-100,0).reshape((10,10)), vmin = -100, vmax =100)
cax = fig.add_axes([ax[1].get_position().x1-0.25,ax[1].get_position().y0,0.02,ax[0].get_position().y1-ax[1].get_position().y0])
fig.colorbar(im1, cax=cax)

Результат

введіть тут опис зображення


@ HS-туманність Дякую за ваші коментарі, і я радий, що вам подобається. :)
Фей Яо

Дійсно дивовижна відповідь. Дякую!!
episodeyang

11

Коли ви створюєте colorbarспробу, використовуючи параметри дробу та / або зменшення.

З документів:

фракція 0,15; фракція оригінальних осей, яку слід використовувати для кольорової панелі

скорочуватися 1,0; фракція, за допомогою якої потрібно зменшити кольорову панель


1
Якщо я встановив скорочення 1,0 і дріб на що-небудь, воно скорочує графік, зовсім не впливаючи на розмір кольорової панелі, поки зміна дробу не призведе до того, що він є саме таким, який я вже маю, і в цей момент їх зміна перестає робити щось.
Елліот

Де саме ви їх вказуєте, вони повинні бути параметрами colorbar()функції чи методу.
Стів Барнс

Дякую. просто потрібно вказати параметр зменшення, і він працює як магія!
CodingNow

11

Всі вищевикладені рішення хороші, але мені подобаються @ @ Стів і @ bejota найкращі, оскільки вони не передбачають вигадливих дзвінків і є універсальними.

Під універсальним я маю на увазі, що працює з будь-якими типами осей, в тому числі GeoAxes. Наприклад, на нього ви спроектували осі для відображення:

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

заклик до

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

не вдасться: KeyException: map_projection

Тому єдиним універсальним способом поводження з розміром кольорової панелі з усіма типами осей є:

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

Працюйте з дробом від 0,035 до 0,046, щоб отримати найкращий розмір. Однак значення для дробу та paddig потрібно буде коригувати, щоб найкраще підходити для вашого сюжету, і відрізнятимуться залежно від того, якщо орієнтація кольорової смуги знаходиться у вертикальному положенні чи горизонталі.


1
Ми також можемо додати shrinkпараметр, коли fractionразом з padне дає достатньо бажаних результатів.
Фей Яо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.