How to draw a precision-recall curve with interpolation in python?
@francis's solution can be vectorized using np.maximum.accumulate
.
import numpy as npimport matplotlib.pyplot as pltrecall = np.linspace(0.0, 1.0, num=42)precision = np.random.rand(42)*(1.-recall)# take a running maximum over the reversed vector of precision values, reverse the# result to match the order of the recall vectordecreasing_max_precision = np.maximum.accumulate(precision[::-1])[::-1]
You can also use plt.step
to get rid of the for
loop used for plotting:
fig, ax = plt.subplots(1, 1)ax.hold(True)ax.plot(recall, precision, '--b')ax.step(recall, decreasing_max_precision, '-r')
A backward iteration can be performed to remove the increasing parts in precision
. Then, vertical and horizontal lines can be plotted as specified in the answer of Bennett Brown to vertical & horizontal lines in matplotlib .
Here is a sample code:
import numpy as npimport matplotlib.pyplot as plt#just a dummy samplerecall=np.linspace(0.0,1.0,num=42)precision=np.random.rand(42)*(1.-recall)precision2=precision.copy()i=recall.shape[0]-2# interpolation...while i>=0: if precision[i+1]>precision[i]: precision[i]=precision[i+1] i=i-1# plotting...fig, ax = plt.subplots()for i in range(recall.shape[0]-1): ax.plot((recall[i],recall[i]),(precision[i],precision[i+1]),'k-',label='',color='red') #vertical ax.plot((recall[i],recall[i+1]),(precision[i+1],precision[i+1]),'k-',label='',color='red') #horizontalax.plot(recall,precision2,'k--',color='blue')#ax.legend()ax.set_xlabel("recall")ax.set_ylabel("precision")plt.savefig('fig.jpg')fig.show()
And here is a result: