Привязать или заблокировать текст к маркеру в Matplotlib

Есть ли способ привязать или заблокировать текст к маркеру? При использовании интерактивного масштабирования, предоставляемого pyplot, текст выходит за границы, как показано на рисунке.

import matplotlib.pyplot as plt

x=[2,4]
y=[2,3]

fig, ax = plt.subplots()
ax.plot(x, y, 'ro',markersize=23)

offset = 1.0 
ax.set_xlim(min(x)-offset, max(x)+ offset)
ax.set_ylim(min(y)-offset, max(y)+ offset)

for x,y in zip(x,y):
     ax.annotate(str(y),  xy=(x-0.028,y-0.028))

plt.show()

Текст выходит за пределы


person Rah    schedule 21.12.2014    source источник


Ответы (1)


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

import matplotlib.pyplot as plt

x=[2,4]
y=[2,3]

fig, ax = plt.subplots()
ax.plot(x, y, 'ro',markersize=23)

offset = 1.0 
ax.set_xlim(min(x)-offset, max(x)+ offset)
ax.set_ylim(min(y)-offset, max(y)+ offset)

for x,y in zip(x,y):
     ax.annotate(str(y),  xy=(x,y))

plt.show()

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

Однако это выглядит довольно некрасиво, так как текст теперь находится в правом верхнем квадранте вашего маркера, а иногда даже лежит за краем маркера. Я предполагаю, что именно по этой причине вы добавили смещение 0,028 в xy=(x-0.028,y-0.028), тем самым вводя поведение, от которого вы сейчас пытаетесь избавиться. Что происходит, так это то, что по умолчанию matplotlib использует систему координат данных для позиционирования вашего текста. Когда вы увеличиваете масштаб, 0,028 единиц данных представляют собой увеличивающуюся долю вашего кадра, а текст «уходит» от вашего маркера, в конечном итоге заканчиваясь за пределами видимого диапазона значений.

Чтобы избавиться от этого поведения, вам нужно изменить систему координат. Аргумент annotate textcoords можно установить равным offset point. Здесь xytext позволяет указать смещение (в пунктах) от позиции xy:

ax.annotate(str(y),  xy=(x,y), xytext=(-5.0,-5.0), textcoords='offset points')

Теперь сложная часть будет состоять в том, чтобы оценить размер текста, который вы хотите добавить на свой график, чтобы определить значение смещения. Скорее всего, текст изменится, но нет возможности определить размер визуализируемой текстовой строки до того, как она будет нарисована. см. этот пост по этому вопросу. В приведенном ниже примере кода , я попытался внести немного гибкости:

import matplotlib.pyplot as plt

x=[2,4]
y=[2,12]

fig, ax = plt.subplots()
ax.plot(x, y, 'ro',markersize=23)

offset = 1.0 
ax.set_xlim(min(x)-offset, max(x)+ offset)
ax.set_ylim(min(y)-offset, max(y)+ offset)

for x,y in zip(x,y):
    text = str(y)
    fontsize, aspect_ratio = (12, 0.5) # needs to be adapted to font
    width = len(text) * aspect_ratio * fontsize 
    height = fontsize
    a = ax.annotate(text,  xy=(x,y), xytext=(-width/2.0,-height/2.0), textcoords='offset points')

plt.show()

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

Здесь текст представляет собой строку длиной 2, и он по-прежнему примерно центрирован относительно маркера, несмотря на сильное масштабирование. Тем не менее, вам нужно будет адаптировать это решение к вашему шрифту и размеру шрифта. Предложения по улучшению очень приветствуются.

person snake_charmer    schedule 26.12.2014