Нулевой элемент массива с соответствующими индексами - PullRequest
0 голосов
/ 21 октября 2018

Я бы хотел обнулить все элементы n-мерного массива, которые находятся в позициях с двумя или более совпадающими индексами.В двух измерениях это фактически np.fill_diagonal(), но эта функция становится неадекватной, когда рассматривается третье измерение.

Ниже приведена грубая версия того, что я хотел бы сделать.Есть ли способ убрать это и заставить его работать в n измерениях?

x = np.ones([3,3,3])

x[:,0,0] = 0
x[0,:,0] = 0
x[0,0,:] = 0

x[:,1,1] = 0
x[1,:,1] = 0
x[1,1,:] = 0

x[:,2,2] = 0
x[2,:,2] = 0
x[2,2,:] = 0

print(x)

1 Ответ

0 голосов
/ 21 октября 2018

В одну сторону np.einsum:

>>> a = np.ones((4,4,4), int)
>>> for n in range(3):
...     np.einsum(f"{'iijii'[n:n+3]}->ij", a)[...] = 0
... 
>>> a
array([[[0, 0, 0, 0],
        [0, 0, 1, 1],
        [0, 1, 0, 1],
        [0, 1, 1, 0]],

       [[0, 0, 1, 1],
        [0, 0, 0, 0],
        [1, 0, 0, 1],
        [1, 0, 1, 0]],

       [[0, 1, 0, 1],
        [1, 0, 0, 1],
        [0, 0, 0, 0],
        [1, 1, 0, 0]],

       [[0, 1, 1, 0],
        [1, 0, 1, 0],
        [1, 1, 0, 0],
        [0, 0, 0, 0]]])

Общий (ND) кейс:

>>> from string import ascii_lowercase
>>> from itertools import combinations
>>> 
>>> a = np.ones((4,4,4,4), int)
>>> n = a.ndim
>>> ltrs = ascii_lowercase[:n-2]
>>> for I in combinations(range(n), 2):
...     li = iter(ltrs)
...     np.einsum(''.join('z' if k in I else next(li) for k in range(n)) + '->z' + ltrs, a)[...] = 0
... 
>>> a
array([[[[0, 0, 0, 0],
         [0, 0, 0, 0],
         [0, 0, 0, 0],
         [0, 0, 0, 0]],

        [[0, 0, 0, 0],
         [0, 0, 0, 0],
         [0, 0, 0, 1],
         [0, 0, 1, 0]],

        [[0, 0, 0, 0],
         [0, 0, 0, 1],
         [0, 0, 0, 0],
         [0, 1, 0, 0]],

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