Масштабирование фигуры для отображения длинных аннотаций - PullRequest
0 голосов
/ 13 апреля 2019

Я аннотировал цветную полосу категориальной тепловой карте с длинными именами. При построении эти имена не полностью видны. plt.tight_layout() нарушает расположение элементов, иногда не показывая отметки тепловой карты или масштабируя цветовую шкалу и тепловую карту вне пропорций. Как я могу автоматически увеличить фигуру, не затрагивая эти другие проблемы?

Вот пример:

import numpy as np

from matplotlib import pyplot as plt
import seaborn as sns
import matplotlib

n_labs = 4
labels = np.floor(np.random.rand(10, 10) * n_labs)
names = np.array(['a'*20] * n_labs)

bounds = np.linspace(-0.5, n_labs - 0.5, n_labs + 1)
norm = matplotlib.colors.BoundaryNorm(bounds, n_labs)
fmt = matplotlib.ticker.FuncFormatter(
    lambda z, pos: names[norm(z)]
)

plt.figure()
plt.suptitle('Title')
sns.heatmap(
    labels, cmap=plt.get_cmap('copper', n_labs), square=True, linewidths=1, vmax=n_labs,
    cbar_kws=dict(
        ticks=np.arange(n_labs), format=fmt,
        boundaries=bounds, drawedges=True
    ),
)
plt.tight_layout()
plt.show()

Результаты без и с tight_layout:

Without

With

1 Ответ

0 голосов
/ 13 апреля 2019

Мне кажется, что Морской Борн делает странные вычисления граничных рамок; несмотря на это, у меня также было много проблем с «умными догадками» plt.tight_layout() раньше, теперь я обычно использую gridspec, чтобы иметь более детальный контроль над макетом рисунка (с дополнительными преимуществами контроля над несколькими подзаговорами):

from matplotlib import gridspec

####
omitting your data code here  for simplicity...
####

fig=plt.figure(figsize=(3,3),dpi=96,) ##### figure size in inch
gs = gridspec.GridSpec(1, 1, ##### a 1x1 subplot grid
    left=0.1,right=0.7,     #####<—— play with these values, 
    bottom=0.0,top=1.0,     #####    they give the margins as percentage of the figure
    wspace=0.0,hspace=0.0,  #####<—- this controls additional padding around the subplot
)
ax = fig.add_subplot(gs[0]) ##### add the gridspec subplot gs[0]

ax.set_title('Title')
sns.heatmap(
    labels, cmap=plt.get_cmap('copper', n_labs), square=True, linewidths=1, vmax=n_labs,
    cbar_kws=dict(
        ticks=np.arange(n_labs), format=fmt,
        boundaries=bounds, drawedges=True,
        shrink=0.6
    ),

    ax=ax #####<—— it is important to let seaborn know which subplot to use
)

--------

Чтобы все было более или менее автоматически , попробуйте построить график так:

fig,axes=plt.subplots(1,2, gridspec_kw = {'width_ratios':[20, 1]},figsize=(3,3))
cbar_ax=axes[1]
ax=axes[0]

ax.set_title('Title')
sns.heatmap(
    labels, cmap=plt.get_cmap('copper', n_labs), square=True, linewidths=1, vmax=n_labs,
    cbar_kws=dict(
        ticks=np.arange(n_labs), format=fmt,
        boundaries=bounds, drawedges=True,
        shrink=0.1,
    ),
    cbar_ax=cbar_ax, #####< it is important to let seaborn know which subplot to use
    ax=ax #####< it is important to let seaborn know which subplot to use
)


plt.tight_layout()    
plt.show()    

Здесь вы создаете два вспомогательных участка (ax и cbar_ax) с width_ratio из 20:1 и затем указываете sns.heatmap, чтобы фактически использовать эти оси. plt.tight_layout(), кажется, работает лучше и максимально автоматически, но все равно столкнется с проблемами (например, установив figsize=(2,2), он выдаст ValueError: left cannot be >= right

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...