Matplotlib: отрегулируйте размер/высоту погрешностей в легенде

Я хотел бы отрегулировать высоту полос ошибок, как показано в легенде matplotlib, чтобы они не сталкивались друг с другом (показано ниже).

Я знаю об этом сообщении Matplotlib: не показывать полосы ошибок в легенде в котором обсуждается, как удалить полосы ошибок, но я не знаю, что нужно сделать, чтобы настроить обработчик так, чтобы полосы ошибок все еще были там, просто укорочены.

Полосы ошибок

Рабочий пример с перекрывающимися полосами ошибок:

import matplotlib
font = {'family' : 'serif',
    'serif': 'Computer Modern Roman',
    'weight' : 'medium',
    'size'   : 19}
matplotlib.rc('font', **font)
matplotlib.rc('text', usetex=True)

fig,ax1=plt.subplots()  
h0=ax1.errorbar([1,2,3],[1,2,3],[1,2,1],c='b',label='$p=5$')
h1=ax1.errorbar([1,2,3],[3,2,1],[1,1,1],c='g',label='$p=5$')
hh=[h0,h1]
ax1.legend(hh,[H.get_label() for H in hh],bbox_to_anchor=(0.02, 0.9, 1., .102),loc=1,labelspacing=0.01, handlelength=0.14, handletextpad=0.4,frameon=False, fontsize=18.5)

Я использую версию 1.5.1 matplotlib, но я не думаю, что это проблема.


person mzzx    schedule 07.09.2017    source источник
comment
По умолчанию должно быть достаточно места между записями легенды; легенда будет выглядеть так. Что вы изменили по сравнению со стандартным? Если вам нужна помощь, вам нужно предоставить минимально воспроизводимый пример кода, с которым у вас возникла проблема (и также четко укажите версию matplotlib, которую вы используете).   -  person ImportanceOfBeingErnest    schedule 07.09.2017
comment
Спасибо - я согласен, мне нужно было использовать ключевое слово labelspacing в легенде, потому что я втискиваю легенду в угол сюжета. Выкладываю код сейчас.   -  person mzzx    schedule 07.09.2017


Ответы (1)


Вы можете использовать kwarg от handler_map до ax.legend для управления дескрипторами легенды.

В этом случае вы хотите использовать обработчик HandlerErrorbar из matplotlib.legend_handler, и установите параметр xerr_size. По умолчанию это 0,5, поэтому нам просто нужно уменьшить это число до чего-то подходящего для сюжета.

Руководствуясь руководством по легенде, мы можем посмотрите, как использовать handler_map. Чтобы просто изменить один из дескрипторов панели ошибок, мы могли бы сделать это:

handler_map={h0: HandlerErrorbar(xerr_size=0.3)}

Предполагая, что вы хотите изменить все дескрипторы панели ошибок таким же образом, вы можете изменить h0 на type(h0):

handler_map={type(h0): HandlerErrorbar(xerr_size=0.3)}

Обратите внимание, что это всего лишь быстрый способ сообщить handler_map, как изменить все Errorbars. Обратите внимание, что это эквивалентно следующим действиям:

from matplotlib.container import ErrorbarContainer
...
ax1.legend(...
    handler_map={ErrorbarContainer: HandlerErrorbar(xerr_size=0.3)}
    ...)

Использование сокращения type(h0) просто означает, что вам не нужно иметь дополнительный импорт ErrorbarContainer.

Объединив это в вашем минимальном примере:

import matplotlib
import matplotlib.pyplot as plt

# Import the handler
from matplotlib.legend_handler import HandlerErrorbar

font = {'family' : 'serif',
    'serif': 'Computer Modern Roman',
    'weight' : 'medium',
    'size'   : 19}
matplotlib.rc('font', **font)
matplotlib.rc('text', usetex=True)

fig,ax1=plt.subplots()  
h0=ax1.errorbar([1,2,3],[1,2,3],[1,2,1],c='b',label='$p=5$')
h1=ax1.errorbar([1,2,3],[3,2,1],[1,1,1],c='g',label='$p=5$')
hh=[h0,h1]
ax1.legend(
        hh, [H.get_label() for H in hh],
        handler_map={type(h0): HandlerErrorbar(xerr_size=0.3)},  # adjust xerr_size to suit the plot
        bbox_to_anchor=(0.02, 0.9, 1., .102),
        loc=1, labelspacing=0.01, 
        handlelength=0.14, handletextpad=0.4,
        frameon=False, fontsize=18.5)

plt.show()

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

Для доказательства того, что это сработало, вы можете сравнить это с исходным изображением до того, как я скорректировал размеры полосы ошибок:

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

person tmdavison    schedule 07.09.2017
comment
Спасибо, это прекрасно работает и очень полезно! Я так понимаю - что делает тип(h0)? Я понимаю, что это меняет все ошибки, но почему? Означает ли это: каждый обработчик типа (h0)? - person mzzx; 07.09.2017
comment
Да, type(h0) — это matplotlib.container.ErrorbarContainer, так что в основном речь идет о том, чтобы управлять всеми ErrorbarContainer одинаково. Я объясню это в своем ответе... - person tmdavison; 07.09.2017
comment
Хорошо, спасибо, я понял. Большое спасибо за объяснение!! - person mzzx; 07.09.2017