실제로 선택한 점을 사용자가 선택한 점을 강조 표시 한 경우 선택한 점 위에 또 다른 점 (dot = ax.scatter(...)
포함)을 겹칠 수 있습니다. 나중에 사용자 클릭에 따라 dot.set_offsets((x, y))
을 사용하여 점의 위치를 변경할 수 있습니다.
Joe Kington은 사용자가 아티스트 (예 : 산점도)를 클릭 할 때 데이터 좌표를 표시하는 주석을 추가하는 방법을 wonderful example (DataCursor
)으로 작성했습니다.
다음은 사용자가 마우스를 한 지점 위로 가져 가면 데이터 요소를 강조 표시하고 주석을 추가하는 파생 예제입니다 (FollowDotCursor
).
DataCursor
은 표시되는 데이터 좌표가 사용자가 클릭하는 위치입니다. 이는 기본 데이터와 정확히 일치하지 않을 수 있습니다.
FollowDotCursor
으로 표시되는 데이터 좌표는 항상 마우스에 가장 가까운 기본 데이터의 한 지점입니다.
import numpy as np
import matplotlib.pyplot as plt
import scipy.spatial as spatial
def fmt(x, y):
return 'x: {x:0.2f}\ny: {y:0.2f}'.format(x=x, y=y)
class FollowDotCursor(object):
"""Display the x,y location of the nearest data point.
"""
def __init__(self, ax, x, y, tolerance=5, formatter=fmt, offsets=(-20, 20)):
try:
x = np.asarray(x, dtype='float')
except (TypeError, ValueError):
x = np.asarray(mdates.date2num(x), dtype='float')
y = np.asarray(y, dtype='float')
self._points = np.column_stack((x, y))
self.offsets = offsets
self.scale = x.ptp()
self.scale = y.ptp()/self.scale if self.scale else 1
self.tree = spatial.cKDTree(self.scaled(self._points))
self.formatter = formatter
self.tolerance = tolerance
self.ax = ax
self.fig = ax.figure
self.ax.xaxis.set_label_position('top')
self.dot = ax.scatter(
[x.min()], [y.min()], s=130, color='green', alpha=0.7)
self.annotation = self.setup_annotation()
plt.connect('motion_notify_event', self)
def scaled(self, points):
points = np.asarray(points)
return points * (self.scale, 1)
def __call__(self, event):
ax = self.ax
# event.inaxes is always the current axis. If you use twinx, ax could be
# a different axis.
if event.inaxes == ax:
x, y = event.xdata, event.ydata
elif event.inaxes is None:
return
else:
inv = ax.transData.inverted()
x, y = inv.transform([(event.x, event.y)]).ravel()
annotation = self.annotation
x, y = self.snap(x, y)
annotation.xy = x, y
annotation.set_text(self.formatter(x, y))
self.dot.set_offsets((x, y))
bbox = ax.viewLim
event.canvas.draw()
def setup_annotation(self):
"""Draw and hide the annotation box."""
annotation = self.ax.annotate(
'', xy=(0, 0), ha = 'right',
xytext = self.offsets, textcoords = 'offset points', va = 'bottom',
bbox = dict(
boxstyle='round,pad=0.5', fc='yellow', alpha=0.75),
arrowprops = dict(
arrowstyle='->', connectionstyle='arc3,rad=0'))
return annotation
def snap(self, x, y):
"""Return the value in self.tree closest to x, y."""
dist, idx = self.tree.query(self.scaled((x, y)), k=1, p=1)
try:
return self._points[idx]
except IndexError:
# IndexError: index out of bounds
return self._points[0]
x = np.random.normal(0,1.0,100)
y = np.random.normal(0,1.0,100)
fig, ax = plt.subplots()
cursor = FollowDotCursor(ax, x, y, formatter=fmt, tolerance=20)
scatter_plot = plt.scatter(x, y, facecolor="b", marker="o")
#update the colour
new_facecolors = ["r","g"]*50
scatter_plot.set_facecolors(new_facecolors)
plt.show()
하나 또는 여러 포인트의 스타일을 같은 시간 (올가미 또는 선택 도구 사용)으로 변경하려는 경우 여러 추가 된 분산 점을 추가하고 추적하는 것이 이상적이지 않습니다. 그러나 주석을 추적한다는 아이디어가 좋고 코드 스 니펫이 매우 잘 작동합니다. – ebarr