Implementing the Trapezoid rule without the formula for the curve I know that if I have some function f(x) that describes a curve, I can approximate the area under the curve using the trapezoid rule as follows:
def auc(f, a, b, n): 
    
    subinterval = (b - a) / n 
      
    s = f(a) + f(b)
    i = 1
    while i &lt; n: 
        s += 2 * f(a + i * subinterval) 
        i += 1
          
    return (subinterval / 2) * s 

However, I am trying to implement the trapezoid rule to approximate the area under the ROC curve. I don't have the function f(x), but rather true positive rates and false positive rates at thresholds from 0 to 1 spaced by .01. I tried to implement the rule following this guide https://byjus.com/maths/trapezoidal-rule/ as so:
def roc_auc(tprs, fprs):
        
    y_sum = max(tprs) + min(tprs)
    for i in range(1, len(fprs)-1):
        y_sum += 2*tprs[i]
    
    interval = (max(fprs) - min(fprs)) / len(fprs)
    return ((interval / 2) * y_sum) / 100

However, when I test it against auc functions implemented in numpy, scikit, etc. I get different values than the one I calculate so I know I'm doing something wrong. Can anyone tell me where I'm going wrong?
You're assuming that the points are equally spaced along the fpr axis, which is generally not true.  See e.g. the &quot;Uniform grid&quot; vs &quot;Nonuniform grid&quot; sections of the wikipedia article.  You need something like
delta_xs = np.diff(fpr)
left_endpoints_y = tpr[:-1]
right_endpoints_y = tpr[1:]
trap_areas = 0.5 * (left_endpoints_y + right_endpoints_y) * delta_xs
area = trap_areas.sum()

(That's more verbose than it needs to be, probably not the most efficient, and I don't know what order your fpr/tpr lists are, so it'll need some finagling.)
Using thresholds at 0.01 spacing is a little unusual too: the ROC curve is represented by using every predicted probability as a threshold (together with $\pm\infty$, or a convention that $(0,0)$ and $(1,1)$ are on the curve).