Uniquify array / list with tolerance in python (equivalent to uniquetol)

I want to find unique array elements in a specific tolerance range

For example, for an array / list

[1.1 , 1.3 , 1.9 , 2.0 , 2.5 , 2.9] 

Function will return

 [1.1 , 1.9 , 2.5 , 2.9] 

If the tolerance is 0.3

in bit, like the MATLAB function http://mathworks.com/help/matlab/ref/uniquetol.html (but this function uses relative tolerance, absolute may be enough) What is the pythonic way to implement it? ( numpy is privileged)

+5
source share
2 answers

With A as the input array and tol as the tolerance value, we could have a vectorized approach with NumPy broadcasting , as well -

 A[~(np.triu(np.abs(A[:,None] - A) <= tol,1)).any(0)] 

Run Example -

 In [20]: A = np.array([2.1, 1.3 , 1.9 , 1.1 , 2.0 , 2.5 , 2.9]) In [21]: tol = 0.3 In [22]: A[~(np.triu(np.abs(A[:,None] - A) <= tol,1)).any(0)] Out[22]: array([ 2.1, 1.3, 2.5, 2.9]) 

Note that 1.9 gone because we had 2.1 within a tolerance of 0.3 . Then 1.1 went for 1.3 and 2.0 for 2.1 .

Note that this will create a unique array with a chain-proximity check. As an example:

 In [91]: A = np.array([ 1.1, 1.3, 1.5, 2. , 2.1, 2.2, 2.35, 2.5, 2.9]) In [92]: A[~(np.triu(np.abs(A[:,None] - A) <= tol,1)).any(0)] Out[92]: array([ 1.1, 2. , 2.9]) 

Thus, 1.3 left due to 1.1 and 1.5 left due to 1.3 .

+3
source

In pure Python 2, I wrote the following:

 a = [1.1, 1.3, 1.9, 2.0, 2.5, 2.9] # Per http://fr.mathworks.com/help/matlab/ref/uniquetol.html tol = max(map(lambda x: abs(x), a)) * 0.3 a.sort() results = [a.pop(0), ] for i in a: # Skip items within tolerance. if abs(results[-1] - i) <= tol: continue results.append(i) print a print results 

The result is

 [1.3, 1.9, 2.0, 2.5, 2.9] [1.1, 2.0, 2.9] 

This is what the spec seems to agree with, but does not match your example.

If I just set the tolerance 0.3 instead of max(map(lambda x: abs(x), a)) * 0.3 , I get:

 [1.3, 1.9, 2.0, 2.5, 2.9] [1.1, 1.9, 2.5, 2.9] 

... that matches your example.

+1
source

All Articles