gesk
gesk

Reputation: 3

comparing numpy arrays with tolerance

I'm trying to compare floating numbers that are stored in numpy arrays. I would like them to be compared with a tolerance and every number of the array should be compared with every number of the other array. My attempt is shown underneath, I used two simple arrays as examples but it has the problem that it only compares numbers with the same indices.

b_y_ion_mass =  np.array([1.000, 2.1300, 3.4320, 6.0000]) 
observed_mass_array = np.array([0.7310, 2.2300, 5.999, 8.000, 9.000])

abs_tol = 0.2 

for (fragment, mass) in zip(b_y_ion_mass, observed_mass_array): 
    if (fragment+abs_tol)> mass and (fragment-abs_tol)< mass:
        print(mass)

It would be great if anyone could help me.

Thank you.

Upvotes: 0

Views: 3569

Answers (2)

Tls Chris
Tls Chris

Reputation: 3824

Use np.isclose with atol = abs_tol.

import numpy as np

b_y_ion_mass =  np.array([1.000, 2.1300, 3.4320, 6.0000]) 
observed_mass_array = np.array([0.7310, 2.2300, 5.999, 8.000, 9.000])
 
abs_tol = 0.2

np.isclose( b_y_ion_mass, observed_mass_array[ :, None ] , atol = abs_tol )
#           columns       rows

# array([[False, False, False, False],
#        [False,  True, False, False],
#        [False, False, False,  True],
#        [False, False, False, False],
#        [False, False, False, False]])

# Compares
#          [1.000, 2.1300, 3.4320, 6.0000]
# [0.7310, 
#  2.2300,         True
#   5.999,                         True 
#   8.000, 
#   9.000]

To get the observed masses:

np.isclose( b_y_ion_mass, observed_mass_array[ :, None ], 
            atol = abs_tol ) * observed_mass_array[ :, None ]

Result

array([[0.   , 0.   , 0.   , 0.   ],
       [0.   , 2.23 , 0.   , 0.   ],
       [0.   , 0.   , 0.   , 5.999],
       [0.   , 0.   , 0.   , 0.   ],
       [0.   , 0.   , 0.   , 0.   ]])

Upvotes: 2

Tom McLean
Tom McLean

Reputation: 6295

You can do:

diff_matrix = b_y_ion_mass - observed_mass_array[:, np.newaxis]

to subtract each item in a by each item in b:

array([[ 2.690e-01,  1.399e+00,  2.701e+00,  5.269e+00],
       [-1.230e+00, -1.000e-01,  1.202e+00,  3.770e+00],
       [-4.999e+00, -3.869e+00, -2.567e+00,  1.000e-03],
       [-7.000e+00, -5.870e+00, -4.568e+00, -2.000e+00],
       [-8.000e+00, -6.870e+00, -5.568e+00, -3.000e+00]])

then take the absolute value and compare to your tolerence:

valid = abs(diff_matrix) < abs_tol

output:

array([[False, False, False, False],
       [False,  True, False, False],
       [False, False, False,  True],
       [False, False, False, False],
       [False, False, False, False]])

So you can see here that the second item in the first array subtract the second item in the second array is less than your tolerance. Also, the last item in your first array subtract the third item in your second array is less than your tolerance

Upvotes: 0

Related Questions