Numpy Диагональ разворота массива - PullRequest
3 голосов
/ 18 июня 2020

Есть ли простой способ в numpy изменить порядок диагонали матрицы на обратное? У меня есть матрица 2x2 вроде этой:

[ 213 5
  198 24 ]

, но я хочу, чтобы она была такой:

[ 24  5
  198 213 ]

Я играл с np.diagonal, но не уверен, как я может сделать это эффективно без al oop.

Ответы [ 2 ]

1 голос
/ 18 июня 2020

Вот один с np.einsum -

def flip_diag(a):
    w = np.einsum('ii->i',a)
    w[:] = w[::-1]
    return a

Другой с np.fill_diagonal -

np.fill_diagonal(a,np.diag(a)[::-1].copy())

Другой с плоской индексацией -

a.flat[::a.shape[1]+1] = a.flat[::-a.shape[1]-1]

Бенчмаркинг

Решения как функции:

# @Quang Hoang's soln
def range_diagonal(a):
    idx = np.arange(len(a))
    a[idx,idx] = np.diagonal(a)[::-1]
    return a    

def fill_diagonal(a):
    np.fill_diagonal(a,np.diag(a)[::-1].copy())
    return a

def flattened_index(a):
    a.flat[::a.shape[1]+1] = a.flat[::-a.shape[1]-1]
    return a

Использование пакета benchit (несколько инструментов тестирования собраны вместе; отказ от ответственности: я являюсь его автором) для тестирования предлагаемых решений.

import benchit

funcs = [range_diagonal, flip_diag, fill_diagonal, flattened_index]
in_ = [np.random.rand(n,n) for n in [2,5,8,20,50,80,200,500,800,2000,5000]]
t = benchit.timings(funcs, in_)
t.plot(logx=True, save='timings.png')

enter image description here

flip_diag и flattened_index выглядят хорошо, и выбор одного из них может быть основан на размерах входного массива.

1 голос
/ 18 июня 2020

Для 2x2 матрицы:

a[::-1].T[::-1]

Для общего n x n:

idx = np.arange(len(a))

a[idx,idx] = np.diagonal(a)[::-1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...