Аннотирование точек данных при построении с Pandas DataFrame
Я хотел бы аннотировать точки данных своими значениями рядом с точками на графике. Примеры, которые я нашел, касаются только x и y в качестве векторов. Тем не менее, я хотел бы сделать это для pandas DataFrame, который содержит несколько столбцов.
ax = plt.figure().add_subplot(1, 1, 1)
df.plot(ax = ax)
plt.show()
Каков наилучший способ аннотировать все точки для многоколоночного DataFrame?
Ответы
Ответ 1
Вы хотите использовать один из других столбцов в качестве текста аннотации? Это то, что я сделал недавно.
Начиная с некоторых примеров данных
In [1]: df
Out[1]:
x y val
0 -1.015235 0.840049 a
1 -0.427016 0.880745 b
2 0.744470 -0.401485 c
3 1.334952 -0.708141 d
4 0.127634 -1.335107 e
Разделите точки. В этом примере я рисую y против x.
In [2]: ax = df.set_index('x')['y'].plot(style='o')
Напишите функцию, которая переплетается над x, y и значение, которое нужно аннотировать рядом с точкой.
In [3]: def label_point(x, y, val, ax):
a = pd.concat({'x': x, 'y': y, 'val': val}, axis=1)
for i, point in a.iterrows():
ax.text(point['x'], point['y'], str(point['val']))
In [4]: label_point(df.x, df.y, df.val, ax)
In [5]: draw()
![Annotated Points]()
Ответ 2
Здесь (очень) немного более гладкая версия Дэн Аллан отвечает:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import string
df = pd.DataFrame({'x':np.random.rand(10), 'y':np.random.rand(10)},
index=list(string.ascii_lowercase[:10]))
Что дает:
x y
a 0.541974 0.042185
b 0.036188 0.775425
c 0.950099 0.888305
d 0.739367 0.638368
e 0.739910 0.596037
f 0.974529 0.111819
g 0.640637 0.161805
h 0.554600 0.172221
i 0.718941 0.192932
j 0.447242 0.172469
И затем:
fig, ax = plt.subplots()
df.plot('x', 'y', kind='scatter', ax=ax)
for k, v in df.iterrows():
ax.annotate(k, v)
Наконец, если вы находитесь в интерактивном режиме, вам может понадобиться обновить график:
fig.canvas.draw()
Что производит:
![Boring scatter plot]()
Или, поскольку это выглядит невероятно уродливым, вы можете немного украсить вещи:
from matplotlib import cm
cmap = cm.get_cmap('Spectral')
df.plot('x', 'y', kind='scatter', ax=ax, s=120, linewidth=0,
c=range(len(df)), colormap=cmap)
for k, v in df.iterrows():
ax.annotate(k, v,
xytext=(10,-5), textcoords='offset points',
family='sans-serif', fontsize=18, color='darkslategrey')
Что выглядит намного приятнее:
![Nice scatter plot]()
Ответ 3
Предположим, что ваш df
имеет несколько столбцов, а три из них - x
, y
и lbl
. Чтобы аннотировать ваш график рассеяния (x,y)
с помощью lbl
, просто:
ax = df.plot.scatter(x='x',y='y')
df[['x','y','lbl']].apply(lambda x: ax.text(*x),axis=1);
Ответ 4
Я нашел, что предыдущие ответы весьма полезны, особенно пример LondonRob, которые немного улучшили макет.
Единственное, что меня беспокоило, это то, что мне не нравится вытаскивать данные из DataFrames, чтобы потом перебирать их. Кажется пустой тратой DataFrame.
Здесь была альтернатива, которая позволяет избежать цикла с использованием .apply() и включает в себя более привлекательные аннотации (я думал, что цветовая гамма немного переборщила и не могла убрать цветную панель):
ax = df.plot('x', 'y', kind='scatter', s=50 )
def annotate_df(row):
ax.annotate(row.name, row.values,
xytext=(10,-5),
textcoords='offset points',
size=18,
color='darkslategrey')
_ = df.apply(annotate_df, axis=1)
![enter image description here]()
Редактировать заметки
Недавно я редактировал мой пример кода. Первоначально он использовал то же самое:
fig, ax = plt.subplots()
поскольку другие сообщения отображают оси, однако это необязательно и делает:
import matplotlib.pyplot as plt
Строка также не нужна.
Также обратите внимание:
- Если вы пытаетесь воспроизвести этот пример, и ваши сюжеты не имеют точек в том же месте, что и любой из наших, это может быть из-за того, что DataFrame использовал случайные значения. Вероятно, это было бы менее запутанным, если бы мы использовали фиксированную таблицу данных или случайное семя.
- В зависимости от точек вам может понадобиться играть со значениями
xytext
, чтобы получить лучшие места размещения.