Pythonic способ проверить, находится ли строка в массиве
Это похоже на простой вопрос, но я не смог найти хороший ответ.
Я ищу pythonic способ проверить, содержит ли массив 2d numpy определенную строку. Например:
myarray = numpy.array([[0,1],
[2,3],
[4,5]])
myrow1 = numpy.array([2,3])
myrow2 = numpy.array([2,5])
myrow3 = numpy.array([0,3])
myrow4 = numpy.array([6,7])
Учитывая myarray, я хочу написать функцию, которая возвращает True, если я тестирую myrow1, и False, если я тестирую myrow2, myrow3 и myrow4.
Я попробовал ключевое слово "in", и он не дал мне ожидаемых результатов:
>>> myrow1 in myarray
True
>>> myrow2 in myarray
True
>>> myrow3 in myarray
True
>>> myrow4 in myarray
False
Кажется, проверяет только то, что один или несколько элементов одинаковы, а не все элементы одинаковы. Может кто-нибудь объяснить, почему это происходит?
Я могу сделать этот тестовый элемент по элементу, примерно так:
def test_for_row(array,row):
numpy.any(numpy.logical_and(array[:,0]==row[0],array[:,1]==row[1]))
Но это не очень pythonic, и становится проблематичным, если строки имеют много элементов. Должно быть более элегантное решение. Любая помощь приветствуется!
Ответы
Ответ 1
Вы можете просто просто вычесть тестовую строку из массива. Затем найдите нулевые элементы и суммируйте по столбцу. Тогда это совпадения, где сумма равна числу столбцов.
Например:
In []: A= arange(12).reshape(4, 3)
In []: A
Out[]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
In []: 3== (0== (A- [3, 4, 5])).sum(1)
Out[]: array([False, True, False, False], dtype=bool)
Обновить: на основе комментариев и других ответов:
Предложение Paul
действительно позволяет упорядочить код:
In []: ~np.all(A- [3, 4, 5], 1)
Out[]: array([False, True, False, False], dtype=bool)
JoshAdel
ответьте в большей степени на проблему, связанную с определением на 100% надежным образом равенства. Итак, очевидно, что мой ответ действителен только в ситуациях, когда равенство может быть определено однозначно.
Обновление 2: но, поскольку Emma
понял это, существуют угловые случаи, когда решение Paul
не даст правильных результатов.
Ответ 2
Вопрос SO ниже должен помочь вам, но в основном вы можете использовать:
any((myrow1 == x).all() for x in myarray)
Numpy.Array в списке Python?
Ответ 3
Это обобщение решения @maz, которое обрабатывает более плавные поплавки, где строгое равенство будет терпеть неудачу:
import numpy as np
def test_for_row(myarray,row):
return any(np.allclose(row,x) for x in myarray)
Подробнее см. http://docs.scipy.org/doc/numpy/reference/generated/numpy.allclose.html. Также обратите внимание на то, что вы не сделали что-то вроде from numpy import *
, так как np.any
и встроенный any
python приведет к разным ответам, первый из которых неверен.
Ответ 4
Я столкнулся с той же проблемой, и для меня работает следующий подход
def is_row_in_matrix(row, matrix):
return sum(np.prod(matrix == row, axis = 1))
В принципе, проверьте, если каждый элемент строки находится в соответствующем столбце матрицы, затем умножьте вдоль столбца (axis = 1)
и суммируйте результат.
Ответ 5
Как насчет:
def row_in_array(myarray, myrow):
return (myarray == myrow).all(-1).any()
Вот как это выглядит для ваших тестовых случаев:
myarray = numpy.array([[0,1],
[2,3],
[4,5]])
row_in_array(myarray, [2, 3])
# True
row_in_array(myarray, [2, 5])
# False
row_in_array(myarray, [0, 3])
# False
row_in_array(myarray, [6, 7])
# False