Диаграмма рассеяния Matplotlib с различным текстом в каждой точке данных

252

Я пытаюсь составить точечный график и аннотировать точки данных различными номерами из списка. Так, например, я хочу построить yпротив xи аннотировать с соответствующими числами из n.

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]
ax = fig.add_subplot(111)
ax1.scatter(z, y, fmt='o')

Любые идеи?

Labibah
источник
Вы также можете получить точечный график с метками всплывающей подсказки при наведении курсора, используя библиотеку mpld3. mpld3.github.io/examples/scatter_tooltip.html
Клод КУЛОМБ

Ответы:

466

Я не знаю ни одного метода построения графиков, который бы использовал массивы или списки, но вы могли бы использовать его для annotate()перебора значений в n.

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.subplots()
ax.scatter(z, y)

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

Существует множество вариантов форматирования annotate(), см. Веб-сайт matplotlib:

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

Рутгер Касси
источник
1
Хорошо работает и на Seaborn regplotбез особых проблем .
Иосиф
@Rutger Я использую dandframe pandas, и я каким-то образом получаю KeyError- так что я предполагаю, что dict()объект ожидается? Есть ли другой способ маркировать данные , используя enumerate, annotateи кадр панды данных?
Рэйчел
@Rachel, вы можете использовать for row in df.iterrows():, а затем получить доступ к значениям row['text'], row['x-coord']и т. Д. Если вы разместите отдельный вопрос, я посмотрю на него.
Рутгер Касси
@RutgerKassies Спасибо, Рутгер! Я разместил здесь вопрос stackoverflow.com/questions/41481153/… Боюсь, что это может быть похоже на этот самый вопрос. Но я не могу решить это как-то. Спасибо за помощь!
Рэйчел
1
@aviator, не встроенный, к сожалению. Но посмотрите, например, это с помощью механизма компоновки networkx: stackoverflow.com/a/34697108/1755432
Рутгер Кэсси
32

В версии более ранней, чем matplotlib 2.0, ax.scatterнет необходимости печатать текст без маркеров. В версии 2.0 вам нужно ax.scatterбудет установить правильный диапазон и маркеры для текста.

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.subplots()

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

И в этой ссылке вы можете найти пример в 3d.

rafaelvalle
источник
Это круто! Спасибо, что поделились этим решением. Можете ли вы также рассказать, что такое правильный код для установки размера фигуры? Такие реализации plt.figure(figsize=(20,10))не работают должным образом, потому что вызов этого кода на самом деле не меняет размер изображения. Ждем вашей помощи. Спасибо!
Левин
fig, ax = plt.subplots (figsize = (20,10))
rafaelvalle
21

В случае, если кто-то пытается применить вышеуказанные решения к .scatter () вместо .subplot (),

Я попытался запустить следующий код

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.scatter(z, y)

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

Но натолкнулся на ошибки, в которых говорилось, что «невозможно распаковать не повторяемый объект PathCollection», а ошибка указывает на кодовую строку fig, ax = plt.scatter (z, y)

Я в конце концов решил ошибку, используя следующий код

plt.scatter(z, y)

for i, txt in enumerate(n):
    plt.annotate(txt, (z[i], y[i]))

Я не ожидал, что будет разница между .scatter () и .subplot (), я должен был знать лучше.

Хизер Клэкстон
источник
11

Вы также можете использовать pyplot.text(см. Здесь ).

def plot_embeddings(M_reduced, word2Ind, words):
""" Plot in a scatterplot the embeddings of the words specified in the list "words".
    Include a label next to each point.
"""
for word in words:
    x, y = M_reduced[word2Ind[word]]
    plt.scatter(x, y, marker='x', color='red')
    plt.text(x+.03, y+.03, word, fontsize=9)
plt.show()

M_reduced_plot_test = np.array([[1, 1], [-1, -1], [1, -1], [-1, 1], [0, 0]])
word2Ind_plot_test = {'test1': 0, 'test2': 1, 'test3': 2, 'test4': 3, 'test5': 4}
words = ['test1', 'test2', 'test3', 'test4', 'test5']
plot_embeddings(M_reduced_plot_test, word2Ind_plot_test, words)

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

irudyak
источник
7

Python 3.6+:

coordinates = [('a',1,2), ('b',3,4), ('c',5,6)]
for x in coordinates: plt.annotate(x[0], (x[1], x[2]))
Палаш
источник
2

Как один вкладыш, использующий списки и numpy:

[ax.annotate(x[0], (x[1], x[2])) for x in np.array([n,z,y]).T]

установка так же, как ответ Рутгера.

Андор Кессельман
источник
1

Я хотел бы добавить, что вы можете даже использовать стрелки / текстовые поля для аннотирования меток. Вот что я имею в виду:

import random
import matplotlib.pyplot as plt


y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.subplots()
ax.scatter(z, y)

ax.annotate(n[0], (z[0], y[0]), xytext=(z[0]+0.05, y[0]+0.3), 
    arrowprops=dict(facecolor='red', shrink=0.05))

ax.annotate(n[1], (z[1], y[1]), xytext=(z[1]-0.05, y[1]-0.3), 
    arrowprops = dict(  arrowstyle="->",
                        connectionstyle="angle3,angleA=0,angleB=-90"))

ax.annotate(n[2], (z[2], y[2]), xytext=(z[2]-0.05, y[2]-0.3), 
    arrowprops = dict(arrowstyle="wedge,tail_width=0.5", alpha=0.1))

ax.annotate(n[3], (z[3], y[3]), xytext=(z[3]+0.05, y[3]-0.2), 
    arrowprops = dict(arrowstyle="fancy"))

ax.annotate(n[4], (z[4], y[4]), xytext=(z[4]-0.1, y[4]-0.2),
    bbox=dict(boxstyle="round", alpha=0.1), 
    arrowprops = dict(arrowstyle="simple"))

plt.show()

Который будет генерировать следующий график: введите описание изображения здесь

Anwarvic
источник