Вот один с 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')
flip_diag
и flattened_index
выглядят хорошо, и выбор одного из них может быть основан на размерах входного массива.