Как сравнить, если любое значение похоже на любое другое, используя numpy - PullRequest
0 голосов
/ 15 июня 2019

У меня есть много пар массивов координат, например:

a=[(1.001,3),(1.334, 4.2),...,(17.83, 3.4)]
b=[(1.002,3.0001),(1.67, 5.4),...,(17.8299, 3.4)]
c=[(1.00101,3.002),(1.3345, 4.202),...,(18.6, 12.511)]

Любая координата в любой из пар может быть дубликатом другой координаты в другом массиве пар.Массивы также имеют разный размер.

Дубликаты будут незначительно различаться по своему значению, и, например, я бы посчитал, что первое значение в a, b и c является дубликатом.

Я мог бы перебирать каждый массив и сравнивать значения одно за другим, используя numpy.isclose, однако это будет медленно.

Существует ли эффективный способ решения этой проблемы, возможно, с помощью numpy, чтобы сократить время вычислений?

Ответы [ 3 ]

0 голосов
/ 15 июня 2019

Возможно, вы захотите взглянуть на numpy.testing, если разрешите обработку AsertionError.

from numpy import testing as ts

a = np.array((1.001,3))
b = np.array((1.000101, 3.002))

ts.assert_array_almost_equal(a, b, decimal=1)  # output None

но

ts.assert_array_almost_equal(a, b, decimal=3)

Результаты в

AssertionError: 
Arrays are not almost equal to 3 decimals
Mismatch: 50%
Max absolute difference: 0.002
Max relative difference: 0.00089891
 x: array([1.001, 3.   ])
 y: array([1.   , 3.002])

В numpy.testing есть еще несколько интересных функций. Обязательно взгляните на документы .

0 голосов
/ 15 июня 2019

Я использую pandas, чтобы дать вам интуитивно понятный результат, а не просто цифры.Конечно, вы можете расширить решение до вашей потребности

Допустим, вы создаете pd.DataFrame из каждого массива и отмечаете их, к какому массиву принадлежит каждый.Я округляю результаты до 2 десятичных знаков, вы можете использовать любой допуск, который вам нужен

dfa = pd.DataFrame(a).round(2)
dfa['arr'] = 'a'

Затем, объединяя, используя duplicated и сортируя, вы можете найти интуитивно понятный Dataframe, который может удовлетворить ваши потребности

df = pd.concat([dfa, dfb, dfc])

df[df.duplicated(subset=[0,1], keep=False)].sort_values(by=[0,1])

выходы

    x       y   arr
0   1.00    3.0 a
0   1.00    3.0 b
0   1.00    3.0 c
1   1.33    4.2 a
1   1.33    4.2 c
2   17.83   3.4 a
2   17.83   3.4 b

Индексы дублируются, поэтому вы можете просто использовать reset_index() в конце и использовать вновь созданный столбец в качестве параметра, который указывает соответствующий индекс накаждый массив.Т.е.:

    index   x       y   arr
0   0       1.00    3.0 a
1   0       1.00    3.0 b
2   0       1.00    3.0 c
3   1       1.33    4.2 a
4   1       1.33    4.2 c
5   2       17.83   3.4 a
6   2       17.83   3.4 b

Так, например, строка 0 обозначает дублирующуюся координату и находится в index 0 из arr a.Строка 1 также указывает координату дублирования, найдено или index 0 из arr b и т. Д.


Теперь, если вы просто хотите удалить дубликаты и получить один финалмассив только с неповторяющимися значениями, вы можете использовать drop_duplicates

df.drop_duplicates(subset=[0,1])[[0,1]].to_numpy()

, что дает

array([[ 1.  ,  3.  ],
       [ 1.33,  4.2 ],
       [17.83,  3.4 ],
       [ 1.67,  5.4 ],
       [18.6 , 12.51]])
0 голосов
/ 15 июня 2019

Вы можете попробовать функцию round (), которая округляет числа в ваших списках до ближайших целых чисел.следующая вещь, которую я бы посоветовал, может быть слишком экстремальной:

объединяет массивы и помещает их в файл данных pandas и drop_duplicates ()

, возможно, это не то решение, которое вам нужно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...