我试图在用户点击有效点时用matplotlib交互式绘制OHLC图。数据存储为表格
的pandas数据帧index PX_BID PX_ASK PX_LAST PX_OPEN PX_HIGH PX_LOW
2016-07-01 1.1136 1.1137 1.1136 1.1106 1.1169 1.1072
2016-07-04 1.1154 1.1155 1.1154 1.1143 1.1160 1.1098
2016-07-05 1.1076 1.1077 1.1076 1.1154 1.1186 1.1062
2016-07-06 1.1100 1.1101 1.1100 1.1076 1.1112 1.1029
2016-07-07 1.1062 1.1063 1.1063 1.1100 1.1107 1.1053
我正在用matplotlib的烛台功能绘图:
candlestick2_ohlc(ax1, df['PX_OPEN'],df['PX_HIGH'],df['PX_LOW'],df['PX_LAST'],width=1)
绘制时看起来像这样:
我希望控制台打印出点击的点的值,日期以及是打开,高低还是关闭。到目前为止,我有类似的东西:
fig, ax1 = plt.subplots()
ax1.set_picker(True)
ax1.set_title('click on points', picker=True)
ax1.set_ylabel('ylabel', picker=True, bbox=dict(facecolor='red'))
line = candlestick2_ohlc(ax1, df['PX_OPEN'],df['PX_HIGH'],df['PX_LOW'],df['PX_LAST'],width=0.4)
def onpick1(event):
if isinstance(event.artist, (lineCollection, barCollection)):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
#points = tuple(zip(xdata[ind], ydata[ind]))
#print('onpick points:', points)
print( 'X='+str(np.take(xdata, ind)[0]) ) # Print X point
print( 'Y='+str(np.take(ydata, ind)[0]) ) # Print Y point
fig.canvas.mpl_connect('pick_event', onpick1)
plt.show()
当我运行此图表时,无论在图表上的任何位置点击它都会出现错误:
AttributeError:'AxesSubplot'对象没有属性'get_xdata'。烛台2_ohlc不支持这个吗?
此外,matplotlibs烛台2_ohlc的实例类型是什么,所以我可以检查用户是否点击了实际点?
例如,对于折线图,可以使用检查
isinstance(event.artist,Line2D)
答案 0 :(得分:1)
首先,candlestick2_ohlc
似乎创建并返回matplotlib.collections.LineCollection
实例和matplotlib.collections.PolyCollection
实例的元组。
在我们做其他事情之前,我们需要让每个实例都可以选择。
如果您从candlestick2_ohlc
返回这些实例时抓取这些实例,则可以轻松使用set_picker
:
linecoll, polycoll = candlestick2_ohlc(ax1, df['PX_OPEN'],df['PX_HIGH'],df['PX_LOW'],df['PX_LAST'],width=0.4)
linecoll.set_picker(True)
polycoll.set_picker(True)
我们需要在onpick1
函数中检查它们:
import matplotlib.collections as collections
def onpick1(event):
# Check we have clicked on one of the collections created by candlestick2_ohlc
if isinstance(event.artist, (collections.LineCollection, collections.PolyCollection)):
thiscollection = event.artist
# Find which box or line we have clicked on
ind = event.ind[0]
# Find the vertices of the object
verts = thiscollection.get_paths()[ind].vertices
if isinstance(event.artist, collections.LineCollection):
print "Errorbar line dimensions"
elif isinstance(event.artist, collections.PolyCollection):
print "Box dimensions"
# Print the minimum and maximum extent of the object in x and y
print( "X = {}, {}".format(verts[:, 0].min(), verts[:, 0].max()) )
print( "Y = {}, {}".format(verts[:, 1].min(), verts[:, 1].max()) )