Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic way to compute sensitivity and specificity

Tags:

python

numpy

I want to compute the sensitivity and specificity of 2 numpy arrays (test, truth). Both arrays have the same shapes and store only the numbers 0 (test/truth false), 1 (test/truth true). Therefore I had to compute the false_positives, true_positives, false_negative and true_negative values. I did it this way:

true_positive = 0
false_positive = 0
false_negative = 0
true_negative = 0

for y in range(mask.shape[0]):
    for x in range(mask.shape[1]):
        if (mask[y,x] == 255 and truth[y,x] == 255):
            true_positive = true_positive + 1
        elif (mask[y,x] == 255 and truth[y,x] == 0):
            false_positive = false_positive + 1
        elif (mask[y,x] == 0 and truth[y,x] == 255):
            false_negative = false_negative + 1
        elif (mask[y,x] == 0 and truth[y,x] == 0):
            true_negative = true_negative + 1

sensitivity = true_positive / (true_positive + false_negative)
specificity = true_negative / (false_positive + true_negative)

I think there could exist a much easier (more readable) way because it's python and not C++ ... First I tried something like: true_positive = np.sum(mask == 255 and truth == 255) but I got this error:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Is there a more pythonic way to compute the sensitivity and specificity?

Thanks!

like image 783
Fabian Avatar asked Sep 19 '26 00:09

Fabian


1 Answers

Focusing on compactness through NumPy supported ufunc-vectorized operations, broadcasting and array-slicing, here's an approach -

C = (((mask==255)*2 + (truth==255)).reshape(-1,1) == range(4)).sum(0)
sensitivity, specificity = C[3]/C[1::2].sum(), C[0]/C[::2].sum()

Alternatively, going a bit NumPythonic, we could have counts C with np.bincount -

C = np.bincount(((mask==255)*2 + (truth==255)).ravel())

To make sure we are getting floating pt numbers as the ratios, at the start, we need to use : from __future__ import division.

like image 200
Divakar Avatar answered Sep 21 '26 15:09

Divakar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!