我用twinx()
在图上得到两个y轴。但是,我希望导航栏报告第一个轴的y坐标。默认情况下,它会将位置报告给第二个轴。如何更改它以报告第一个轴,或者更好的是报告它们?
答案 0 :(得分:20)
在tcaswell的答案(here和here)的帮助下,您可以修改跟踪器以显示相对于两个轴的坐标,如下所示:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
def make_format(current, other):
# current and other are axes
def format_coord(x, y):
# x, y are data coordinates
# convert to display coords
display_coord = current.transData.transform((x,y))
inv = other.transData.inverted()
# convert back to data coords with respect to ax
ax_coord = inv.transform(display_coord)
coords = [ax_coord, (x, y)]
return ('Left: {:<40} Right: {:<}'
.format(*['({:.3f}, {:.3f})'.format(x, y) for x,y in coords]))
return format_coord
np.random.seed(6)
numdata = 100
t = np.linspace(0.05, 0.11, numdata)
y1 = np.cumsum(np.random.random(numdata) - 0.5) * 40000
y2 = np.cumsum(np.random.random(numdata) - 0.5) * 0.002
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax2.format_coord = make_format(ax2, ax1)
ax1.plot(t, y1, 'r-', label='y1')
ax2.plot(t, y2, 'g-', label='y2')
plt.show()
或者,如果你有scipy,你可以使用FollowDotCursor
,它将注释最接近光标的数据点。通过这种方式,用户的眼睛不必远离图形来查找数据坐标。此外,它可以应用于两个以上的艺术家(只需为每一行添加一个FollowDotCursor,散点图,条形图等)。
它也更准确,因为注释窗口显示最近数据点的值,而不仅仅是数据坐标中光标的坐标。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
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.
https://stackoverflow.com/a/4674445/190597 (Joe Kington)
https://stackoverflow.com/a/20637433/190597 (unutbu)
"""
def __init__(self, ax, x, y, 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')
mask = ~(np.isnan(x) | np.isnan(y))
x = x[mask]
y = y[mask]
self._points = np.column_stack((x, y))
self.offsets = offsets
y = y[np.abs(y - y.mean()) <= 3 * y.std()]
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.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))
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]
np.random.seed(6)
numdata = 100
t = np.linspace(0.05, 0.11, numdata)
y1 = np.cumsum(np.random.random(numdata) - 0.5) * 40000
y2 = np.cumsum(np.random.random(numdata) - 0.5) * 0.002
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()
ax1.plot(t, y1, 'r-', label='y1')
ax2.plot(t, y2, 'g-', label='y2')
cursor1 = FollowDotCursor(ax1, t, y1)
cursor2 = FollowDotCursor(ax2, t, y2)
plt.show()
答案 1 :(得分:3)
导航栏显示位于顶部的轴的坐标。因此,您要做的就是使右轴的zorder
低于左轴的{>
ax2.set_zorder(-100)
这也将改变图形的外观。也就是说,在右轴上绘制的所有内容都将在在左轴上绘制的所有内容后面。在许多情况下,这几乎没有差别。