Как проверить, совпадают ли все значения в столбцах матрицы numpy?
Я хочу проверить, совпадают ли все значения в столбцах массива numpy/matrix.
Я попытался использовать reduce
ufunc equal
, но, похоже, он не работает во всех случаях:
In [55]: a = np.array([[1,1,0],[1,-1,0],[1,0,0],[1,1,0]])
In [56]: a
Out[56]:
array([[ 1, 1, 0],
[ 1, -1, 0],
[ 1, 0, 0],
[ 1, 1, 0]])
In [57]: np.equal.reduce(a)
Out[57]: array([ True, False, True], dtype=bool)
In [58]: a = np.array([[1,1,0],[1,0,0],[1,0,0],[1,1,0]])
In [59]: a
Out[59]:
array([[1, 1, 0],
[1, 0, 0],
[1, 0, 0],
[1, 1, 0]])
In [60]: np.equal.reduce(a)
Out[60]: array([ True, True, True], dtype=bool)
Почему средний столбец во втором случае также оценивается как True
, тогда как он должен быть False
?
Спасибо за любую помощь!
Ответы
Ответ 1
In [45]: a
Out[45]:
array([[1, 1, 0],
[1, 0, 0],
[1, 0, 0],
[1, 1, 0]])
Сравните каждое значение с соответствующим значением в первой строке:
In [46]: a == a[0,:]
Out[46]:
array([[ True, True, True],
[ True, False, True],
[ True, False, True],
[ True, True, True]], dtype=bool)
Столбец имеет общее значение, если все значения в этом столбце равны True:
In [47]: np.all(a == a[0,:], axis = 0)
Out[47]: array([ True, False, True], dtype=bool)
Проблема с np.equal.reduce
может быть замечена путем микроанализа, что происходит, когда оно применяется к [1, 0, 0, 1]
:
In [49]: np.equal.reduce([1, 0, 0, 1])
Out[50]: True
Первые два элемента 1
и 0
проверяются на равенство, а результат False
:
In [51]: np.equal.reduce([False, 0, 1])
Out[51]: True
Теперь False
и 0
проверяются на равенство, а результат True
:
In [52]: np.equal.reduce([True, 1])
Out[52]: True
Но True
и 1 равны, поэтому общий результат True
, что не является желаемым результатом.
Проблема заключается в том, что reduce
пытается скопировать результат "локально", в то время как нам нужен "глобальный" тест, например np.all
.
Ответ 2
Учитывая ubuntu удивительное объяснение, вы можете использовать reduce
для решения своей проблемы, но вы должны применить его к bitwise_and
и bitwise_or
, а не к equal
. Как следствие, это не будет работать с массивами с плавающей запятой:
In [60]: np.bitwise_and.reduce(a) == a[0]
Out[60]: array([ True, False, True], dtype=bool)
In [61]: np.bitwise_and.reduce(b) == b[0]
Out[61]: array([ True, False, True], dtype=bool)
В принципе, вы сравниваете бит каждого элемента в столбце. Идентичные биты не изменяются. Различные биты устанавливаются на ноль. Таким образом, любое число, которое имеет нуль вместо одного бита, изменит приведенное значение. bitwise_and
не будет улавливать случай, когда биты вводятся, а не удаляются:
In [62]: c = np.array([[1,0,0],[1,0,0],[1,0,0],[1,1,0]])
In [63]: c
Out[63]:
array([[1, 0, 0],
[1, 0, 0],
[1, 0, 0],
[1, 1, 0]])
In [64]: np.bitwise_and.reduce(c) == c[0]
Out[64]: array([ True, True, True], dtype=bool)
Второй кумин явно ошибочен. Нам нужно использовать bitwise_or
для захвата новых бит:
In [66]: np.bitwise_or.reduce(c) == c[0]
Out[66]: array([ True, False, True], dtype=bool)
Итоговый ответ
In [69]: np.logical_and(np.bitwise_or.reduce(a) == a[0], np.bitwise_and.reduce(a) == a[0])
Out[69]: array([ True, False, True], dtype=bool)
In [70]: np.logical_and(np.bitwise_or.reduce(b) == b[0], np.bitwise_and.reduce(b) == b[0])
Out[70]: array([ True, False, True], dtype=boo
In [71]: np.logical_and(np.bitwise_or.reduce(c) == c[0], np.bitwise_and.reduce(c) == c[0])
Out[71]: array([ True, False, True], dtype=bool)
Этот метод более ограничительный и менее элегантный, чем ubunut предложение использования all
, но оно имеет то преимущество, что не создает огромные временные массивы, если ваш вход огромен. Временные массивы должны быть такими же большими, как первая строка вашей матрицы.
ИЗМЕНИТЬ
Основываясь на этом Q/A и ошибка, которую я подал с помощью numpy, решение предоставляется только потому, что ваш массив содержит нули и единицы. Как бы то ни было, показанные операции bitwise_and.reduce()
могут возвращать только нуль или один, потому что bitwise_and.identity
есть 1
, а не -1
. Я сохраняю этот ответ в надежде, что numpy
фиксируется, и ответ становится действительным.
Edit
Похоже, на самом деле скоро произойдет изменение в numpy. Конечно, bitwise_and.identity
, а также, возможно, необязательный параметр для уменьшения.
Edit
Хорошая новость. Идентификатор для np.bitwise_and
был установлен в -1
с версии 1.12.0
.