Как согласовать аннотацию точек на точечной диаграмме Matplotlib с ручной настройкой предела?

avatar
alexnesov
18 января 2020 в 21:54
215
2
1

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

Вот мой код:

fig, ax = plt.subplots(figsize = (20,10)) #manual limit setting
plt.axis([-2,3,-2.5,5])
plt.scatter(x, y)


for i, txt in enumerate(n):   #dot annotation   
    ax.annotate(txt, (x[i], y[i]))

Вот скриншот вывода (я получил окончательный точечный график в виде маленького прямоугольника, расположенного в левом углу большого белого прямоугольника:

Output

Я также пробовал:

 fig, ax = plt.subplots(figsize = (20,10))
    ax = plt.axis([-2,3,-2.5,5])
    plt.scatter(x, y)


for i, txt in enumerate(n):
    ax.annotate(txt, (x[i], y[i]))

Но, конечно, я получил следующее сообщение об ошибке (хотя диаграмма отображается правильно, но без меток рядом с каждой соответствующей точкой).

AttributeError: 'list' object has no attribute 'annotate'

Ошибка возникает из-за того, что мой цикл пытается выполнить итерацию через ax = plt.axis([-2,3,-2.5,5]), что на самом деле не имеет смысла.

Есть ли решение этой проблемы?

Спасибо

Источник
ImportanceOfBeingErnest
18 января 2020 в 23:03
0

Какую версию matplotlib вы используете? Эта проблема все еще возникает в matplotlib 3.1.2? (Я думаю, что это уже исправлено, но если нет, было бы полезно знать.)

Ответы (2)

avatar
ImportanceOfBeingErnest
20 января 2020 в 13:17
6

Проблема возникает из-за особого регистра текста при вырезании. Обычно вы можете захотеть, чтобы текст отображался за пределами осей. Поэтому аннотации и текст имеют аргумент annotation_clip. Однако это мешает опции bbox_inches="tight" при сохранении аннотаций, потому что аннотации в этом случае по-прежнему считаются частью компоновки, и, следовательно, фигура по-прежнему учитывает аннотации за пределами осей.

Два решения:

  1. Набор annotation_clip и clip_on. т.е. Вы можете явно указать аннотации обрезать по осям:

    ax.annotate(txt, (x[i], y[i]), annotation_clip=True, clip_on=True)
    
  2. Установите bbox_inches на None. При использовании встроенного бэкенда IPython вы можете указать ему не расширять фигуру через

    %config InlineBackend.print_figure_kwargs = {'bbox_inches':None}
    

    в ячейке, прежде чем начать создавать контент. (Это видно в этом ответе)

William Miller
20 января 2020 в 22:11
0

Таким образом, неправильный размер в вопросе вызван размещением текста за пределами осей? Или я неправильно понимаю?

ImportanceOfBeingErnest
20 января 2020 в 22:28
0

@WilliamMiller Правильно. К сожалению, они не предоставили минимальный воспроизводимый пример, поэтому нужно немного интерпретировать. Для воспроизведения используйте, например. x = y = [-1,2,9] и запустите код в блокноте IPython или Jupyter со встроенной серверной частью.

William Miller
20 января 2020 в 22:31
0

Интересно, спасибо - еще один вопрос: знаете ли вы, почему текст не отображается на изображении в вопросе? Почему сверху и справа от осей просто пустое пространство?

ImportanceOfBeingErnest
21 января 2020 в 01:52
1

@WilliamMiller Эти тексты не нарисованы, но они учитываются при расчете узких боксов.

avatar
William Miller
19 января 2020 в 04:49
1

Я не могу воспроизвести первую проблему (пробовал в версиях 2.2.3, 3.1.1, 3.1.2) - я получаю это (используя случайные данные). Попробуйте обновить свою версию matplotlib или использовать

plt.savefig('/path/to/output/image.png')

Чтобы сохранить рисунок на диск вместо того, чтобы показывать его напрямую, и посмотреть, сохраняется ли проблема.

Однако я могу объяснить ошибку

AttributeError: 'list' object has no attribute 'annotate'

Это происходит потому, что plt.axis() возвращает [xmin, xmax, ymin, ymax], а не экземпляр axes (fig, ax = plt.subplots(figsize=(20,10) возвращает экземпляр axes в ax).<27068307>0.

alexnesov
19 января 2020 в 11:17
0

У меня последняя версия (3.1.2). Он по-прежнему отображает график в странном дизайне, но когда я его экспортирую, он работает! Спасибо

William Miller
19 января 2020 в 16:13
0

@alexnesov Нет проблем, не забудьте нажать «Принять», если это помогло решить проблему — таким образом вопрос будет помечен как таковой для будущих пользователей.

alexnesov
19 января 2020 в 18:38
0

Извините я забыл :)

William Miller
19 января 2020 в 18:42
0

@alexnesov Не беспокойтесь