#python #numpy
Вопрос:
Даны 2 массива numpy A и B, как показано ниже :
A =
[[ 1, 200, 15],
[ 0, 600, 25],
[ 2, 200, 20],
[ 3, 100, 10],
[ 1, 300, 5],
[ 4, 400, 3],
[ 0, 100, 12],
[ 5, 300, 2],
[ 2, 300, 25],
[ 6, 100, 1],
[ 1, 400, 74],
[ 7, 300, 10],
[ 2, 400, 15],
[ 8, 200, 13],
[ 3, 400, 29],
[ 3, 600, 37],
[ 0, 200, 20],
[ 9, 300, 42],
[ 5, 400, 30],
[ 6, 200, 51],
[ 7, 400, 21],
[ 9, 500, 5],
[ 10, 300, 9] ]
B =
[[ 0, 25.],
[ 1, 74.],
[ 2, 25.],
[ 3, 37.],
[ 4, 3.],
[ 5, 30.],
[ 6, 51.],
[ 7, 21.],
[ 8, 13.],
[ 9, 42.],
[10, 9.]]
Каков эффективный способ (без цикла FOR) вычисления индексов строк в массиве A
, где столбцы 0 и 2 A образуют массив B?
Ожидаемый ответ-я:
i = [ 1, 5, 8, 10, 13, 15, 17, 18, 19, 20, 22]
Так что:
A[i,:] == B
Заранее благодарю вас
Ответ №1:
Вы могли бы сделать следующее:
- Начните с захвата первого и третьего столбцов
A
с>>> A[:,(0,2)]
- Затем сравните все возможные пары строк
(A[i], B[j])
с помощьюbroadcasting
трюка иnp.equal
:>>> np.equal(A[:,(0,2)][:,None], B[None])
- Убедитесь, что все элементы в строке совпадают, используя
np.all
:>>> np.equal(A[:,(0,2)][:,None], B[None]).all(2)
- Наконец, посмотрите на argmax на первой оси, это предполагает, что есть по крайней мере одно совпадение
A
для каждой строкиB
:>>> np.equal(A[:,(0,2)][:,None], B[None]).all(2).argmax(0)
Приведенная выше строка не будет работать, например, если вы удалите
B
последнюю строку. В одной из строк все равные условия являются ложными (вообще не совпадаютB
), но argmax все равно выберет первоеFalse
значение, т. е. возвращающий индекс0
… что не является очень общим решением.Более точный метод состоит в том, чтобы
np.nonzero
вместо этого использовать только ненулевые значения, что именно то, что мы здесь хотим:>>> np.equal(A[:,(0,2)][:,None], B[None]).all(2).nonzero()[0]
Комментарии:
1. Можете ли вы немного объяснить «трюк с трансляцией»? Я видел это несколько раз, но мне трудно представить, что именно здесь происходит. Спасибо.
2. Этот трюк включает в себя добавление дополнительного измерения с противоположных сторон. Возьмем этот пример:
A = np.arange(1,4)
иB = np.arange(1,4)
. ТогдаA[None]
будет иметь форму(1, 3)
, в то времяB[:, None]
как будет иметь форму(3, 1)
. При использовании в сочетании с оператором (выше это былоnp.equal
), тогда операция не будет выполняться по элементам (это было бы в случае , если бы вы далиA
, иB
), а вместо этого будут рассмотрены все комбинации пар. Наглядным примером является*
оператор:A*B
является ли элементарный продукт, в то времяA[None]*B[:,None]
как внешний продукт междуA
иB
.3. Огромное спасибо. Думаю, теперь он у меня есть. Я ценю то время, что вы добровольно согласились на ЭТО. Будьте в безопасности и оставайтесь здоровыми.
4. Спасибо, Иван, это работает…