Matplotlib指示X和Y轴上的点

时间:2017-02-20 16:44:43

标签: python matplotlib plot

我经常想要使用matplotlib突出显示曲线上的一个点,以制作如下情节: Basic Plot

以下代码用于创建情节

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

y  = np.array([0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100])/100.
x = 100. - np.array([
    99.79,98.96,98.65,98.39,98.13,97.88,97.61,97.33,97.01,96.65,96.21,
    95.72,95.16,94.46,93.52,92.31,90.66,88.48,84.04,79.34,19.32])
ax = plt.subplot(111)
line = plt.plot(x,y)


def highlight_point(ax,line,point,linestyle=':'):
    c = line.get_color()
    xmin = ax.get_xlim()[0]
    ymin = ax.get_ylim()[0]

    ax.plot([xmin,point[0]],[point[1],point[1]],color=c,linestyle=linestyle)
    ax.plot([point[0],point[0]],[ymin,point[1]],color=c,linestyle=linestyle)

plt.xlim([0,85])
plt.ylim([0,1])
highlight_point(ax,line[0],[x[10],y[10]])
plt.show()

如果未能输入xlimylim,或者稍后将另一个图添加到图中,则上述方法会失败。我想要axhlinehlines的某种组合,我可以将图的左/底指定为某个数学点。

1 个答案:

答案 0 :(得分:2)

一种方法可以是每次重绘画布时更新线条。为此,我们可以创建一个类PointMarkers,其中包含一个连接到draw_event侦听器的更新方法。这样,不仅在创建标记线后添加点,而且在调整画布大小或平移画布时,线条也会更新。

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

class PointMarker():
    def __init__(self, ax, point, **kwargs):
        self.ax = ax
        self.point = point
        if "line" in kwargs:
            self.c = kwargs.get("line").get_color()
        else:
            self.c = kwargs.get("color", "b")
        self.ls=kwargs.get("linestyle", ':')
        self.vline, = self.ax.plot([],[],color=self.c,linestyle=self.ls)
        self.hline, = self.ax.plot([],[],color=self.c,linestyle=self.ls)
        self.draw()

    def draw(self):
        xmin = ax.get_xlim()[0]
        ymin = ax.get_ylim()[0]
        self.vline.set_data([self.point[0], self.point[0]], [ymin,self.point[1]])
        self.hline.set_data([xmin, self.point[0]], [self.point[1], self.point[1]])

class PointMarkers():
    pointmarkers = []
    def add(self,ax, point, **kwargs ):
        pm = PointMarker(ax, point, **kwargs)
        self.pointmarkers.append(pm)
    def update(self, event=None):
        for pm in self.pointmarkers:
            pm.draw()

x = np.arange(1,17)
y = np.log(x)
ax = plt.subplot(111)
line = plt.plot(x,y)

# register the markers
p = PointMarkers()
p.add(ax,[x[5],y[5]], line=line[0])
p.add(ax,[x[12],y[12]], color="purple", linestyle="-.")
# connect event listener
cid = plt.gcf().canvas.mpl_connect("draw_event", p.update)

#testing: draw some new points or change axis limits
plt.plot([5,11],[-0.5,0.6])
#plt.xlim([0,85])
#plt.ylim([0,1])

plt.show()

enter image description here

对于保存,需要在保存命令之前直接手动执行重绘,如

plt.gcf().canvas.draw()
plt.savefig(...)