Как я могу сравнить два массива с разными размерами, но с приблизительными значениями с плавающей точкой? [Python3]

#python-3.x #numpy #floating-point #compare #precision

#python-3.x #numpy #с плавающей запятой #Сравнить #точность

Вопрос:

Как я могу сравнить два массива с разными размерами, но с приблизительными значениями с плавающей точкой? Например:

 # I have two arrays
a = np.array( [-2.83, -2.54, ..., 0.05, ..., 2.54, 2.83] )
b = np.array( [-3.0, -2.9, -2.8, ..., -0.1, 0.0, 0.1, ..., 2.9, 3.0] )
# wherein len( b ) > len( a )
  

Что мне нужно, так это индекс where (учитывая эти два значения из обоих списков)

 math.isclose( -2.54, -2.5, rel_tol=1e-1) == True
  

Ответ, который мне нужен, это что-то вроде

 list_of_index_of_b = [1, 5, ..., -2]
  

Вот list_of_index_of_b список с «координатами», где этот конкретный элемент b является приблизительным к некоторому элементу a . Не все элементы a имеют приблизительное значение b . Также:
len(list_of_index_of_b) == len(a)

Комментарии:

1. len(list_of_index_of_b) == len(a) ?

2. Если a и b не слишком велики, простым методом было бы np.where(np.isclose(*np.ix_(a, b), rtol=1e-1)) .

Ответ №1:

Вы можете использовать широковещательную передачу. Это создает массив попарных различий между каждым элементом в a и b , который затем вы можете проверить на соответствие указанному допуску.

Конечно, это вычислительно неэффективно с точки зрения сложности, поскольку вы создаете массив размера |a|*|b| и сравниваете каждое попарное расстояние с допуском, даже если одно из различий уже достаточно мало. Тем не менее, если один из |a| или |b| относительно мал, то этот подход может быть довольно быстрым, поскольку он является чисто numpy и не требует циклов.

 a = np.array([1,5,6,7])
b = np.array([1.1,2,3,4.8,4.9,5,8])

rtol = 0.15

diff = a - b[:,None]
mask2d = (1/np.abs(b))*np.abs(a - b[:,None]) < rtol

mask = np.any(mask2d,axis=1)
  

Это можно объединить в одну строку:

 indices = np.where(np.any((1/np.abs(b))*np.abs(a-b[:,None]) < rtol,axis=1))