Маркировка точек данных python на графике

#python #matplotlib #linechart #subplot

#python #matplotlib #метка #аннотировать

Вопрос:

Я искал целую вечность (часы, которые похожи на возраст), чтобы найти ответ на действительно раздражающую (казалось бы, базовую) проблему, и поскольку я не могу найти вопрос, который вполне соответствует ответу, я отправляю вопрос и отвечаю на него в надежде, что это сэкономит кому-то еще огромное количество времени, которое япросто потратил на мои навыки рисования noobie.

Если вы хотите пометить свои точки графика с помощью python matplotlib

 from matplotlib import pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

A = anyarray
B = anyotherarray

plt.plot(A,B)
for i,j in zip(A,B):
    ax.annotate('%s)' %j, xy=(i,j), xytext=(30,0), textcoords='offset points')
    ax.annotate('(%s,' %i, xy=(i,j))

plt.grid()
plt.show()
  

Я знаю, что xytext=(30,0) соответствует текстовым координатам, вы используете эти значения 30,0 для позиционирования точки метки данных, поэтому она находится на оси 0 y и на 30 выше по оси x на своей собственной небольшой области.

Вам нужны обе линии, отображающие i и j, в противном случае вы наносите только метки данных x или y.

Вы получаете что-то вроде этого (обратите внимание только на метки):
Мой собственный график с помеченными точками данных

Это не идеально, все еще есть некоторое перекрытие, но это лучше, чем ничего, что у меня было..

Комментарии:

1. Почему бы просто не сделать ax.annotate('(%s, %s)' % (i, j), ...) ? (Или, если вы используете форматирование строк в более новом стиле, '({}, {})'.format(i, j) .)

2. оставляя это здесь matplotlib.org/users/annotations.html

3. pyplot.text, похоже, является альтернативой аннотации: pythonmembers.club/2018/05/08/… Не уверен, что это делает что-то другое, хотя

4. Сопровождающий pythonmembers.club здесь. XD это то, что меня раздражало как новичка. Эта статья стала достаточно популярной, чтобы ее включили в курс НЛП Стэнфордского университета (выделена жирным шрифтом прямая ссылка на статью)

Ответ №1:

Как насчет печати (x, y) сразу.

 from matplotlib import pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

A = -0.75, -0.25, 0, 0.25, 0.5, 0.75, 1.0
B = 0.73, 0.97, 1.0, 0.97, 0.88, 0.73, 0.54

ax.plot(A,B)
for xy in zip(A, B):                                       # <--
    ax.annotate('(%s, %s)' % xy, xy=xy, textcoords='data') # <--

ax.grid()
plt.show()
  

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

Комментарии:

1. Просто примечание для всех, кто использует это: textcoords=’offset points’, похоже, оказывает переменный эффект в зависимости от масштаба графика (для меня это приводило к тому, что большинство меток появлялись вне графика)

2. Да, вместо этого вы должны использовать textcoords=’data’ .

3. @navari, спасибо за информацию. Я соответствующим образом обновил ответ.

4. @EricG — я считаю, что для этого textcoords='offset points' также требуется xytext параметр. Другими словами, установите xytext=(x points, y points) для смещения и textcoords='offset points' будет работать так, как вы ожидаете.

5. @PrasantaBandyopadhyay, используй оператор if; условно аннотируй в соответствии со значением x.

Ответ №2:

У меня была похожая проблема, и в итоге получилось так:

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

Для меня это имеет то преимущество, что данные и аннотации не перекрываются.

 from matplotlib import pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111)

A = -0.75, -0.25, 0, 0.25, 0.5, 0.75, 1.0
B = 0.73, 0.97, 1.0, 0.97, 0.88, 0.73, 0.54

plt.plot(A,B)

# annotations at the side (ordered by B values)
x0,x1=ax.get_xlim()
y0,y1=ax.get_ylim()
for ii, ind in enumerate(np.argsort(B)):
    x = A[ind]
    y = B[ind]
    xPos = x1   .02 * (x1 - x0)
    yPos = y0   ii * (y1 - y0)/(len(B) - 1)
    ax.annotate('',#label,
          xy=(x, y), xycoords='data',
          xytext=(xPos, yPos), textcoords='data',
          arrowprops=dict(
                          connectionstyle="arc3,rad=0.",
                          shrinkA=0, shrinkB=10,
                          arrowstyle= '-|>', ls= '-', linewidth=2
                          ),
          va='bottom', ha='left', zorder=19
          )
    ax.text(xPos   .01 * (x1 - x0), yPos,
            '({:.2f}, {:.2f})'.format(x,y),
            transform=ax.transData, va='center')

plt.grid()
plt.show()
  

Использование текстового аргумента в .annotate привело к неблагоприятным позициям текста.
Рисование линий между легендой и точками данных — это беспорядок, так как местоположение легенды трудно определить.