'Intersect float rows in two numpy matrices with precision
I'm looking for rows in B which are close to any of the rows in A
example: eps = 0.1
A = [[1.22, 1.33], [1.45, 1.66]]
B = [[1.25, 1.34], [1.77, 1.66], [1.44, 1.67]]
Result: [[1.22, 1.33], [1.45, 1.66]]
Solution 1:[1]
If you are looking to filter to elements in A
which are close to any element in B
, you can use broadcast
and tile
to do an exhaustive check:
import numpy as np
eps = .1
A = np.array([[1.22, 1.33], [1.45, 1.66]])
B = np.array([[1.25, 1.34], [1.77, 1.66], [1.44, 1.67]])
# broadcast A based on the shape of B
A_ext = np.broadcast_to(A, (B.shape[0],) + A.shape)
# tile B and reshape, this will allow comparison of all elements in A to all elements in B
B_ext = np.tile(B, A.shape[0]).reshape(A_ext.shape)
# create the boolean array
A_bool = np.abs(A_ext - B_ext) < eps
# reduce array to match number of elements in A
# .all() will result in an array representing which elements in A are close to each element in B
# .any() represents if A is close to any of the elements in B
A_mask = A_bool.all(axis = -1).any(axis = 0)
# final result
A[A_mask]
Solution 2:[2]
I agree with Professor Pantsless' comment and would expand on it's use here:
Your arrays look like so:
# array A
1.22 1.33
1.45 1.66
# array B
1.25 1.34
1.77 1.66
Your desired result (per your OP) matches to A[0]
, or 1.22 1.33
. This indicates that you wish to return an array of the rows inside array A
in which all elements in a row are < eps
when compared to the same indexed row of array 'B':
# array C
np.abs(A[0] - B[0]) # --> True True
np.abs(A[1] - B[1]) # --> False True
This is achievable with a boolean index achieved using:
>>> A[(np.abs(A-B) < eps).all(axis = 1)]
Breaking down this line:
>>> np.abs(A-B)
0.03 0.01
0.32 0.00
>>> np.abs(A-B) < eps
True True
False True
# notice this matches the comments above
>>> (np.abs(A-B) < eps).all(axis = 1)
True False
The (np.abs(A-B) < eps)
returns a new array of booleans, and the .all(axis = 1)
checks along the first axis (so column wise) of each row to see if all elements per row are True
. Since the first row of array C
is all True
, it returns True
; this does not hold for the second row as its False True
so it returns False
. What you're left with is an array of shape (N, )
.
So now the final breakdown is:
>>> A[(np.abs(A-B) < eps).all(axis = 1)]
1.22 .133
# since this is access A like A[(True, False)]
w.r.t. your latest comment, you cannot do that because of NumPy's broadcasting rules. These rules are pretty similar to standard matrix multiplication rules. So you cannot take a 2x2
matrix and multiply by a 3x2
because the inner dimensions don't work.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Professor Pantsless |
Solution 2 | pstatix |