Создание трехмерного (или большего) диагонального массива NumPy из диагоналей

#python-3.x #numpy #numpy-ndarray

#python-3.x #numpy #numpy-ndarray

Вопрос:

Существует ли эффективное решение на основе «Numpy» для создания 3-х (или более высокой) размерной диагональной матрицы?

Более конкретно, я ищу более короткое (и, возможно, более эффективное) решение для замены следующего:

 N = 100
M = 4
d = np.random.randn(N)   # calculated in the real use case from other parameters
A = np.zeros(M, M, N, dtype=d.dtype)
for i in range(M):
    A[i, i, :] = d
  

Вышеупомянутое решение будет медленным, если M оно большое, и я думаю, что оно не очень экономично с точки зрения памяти, поскольку d оно копируется M раз в памяти.

Ответ №1:

Вот один с np.einsum diag-view —

 np.einsum('iij->ij',A)[:] =  d
  

Глядя на строковую нотацию, это также хорошо переводится из итеративной части : A[i, i, :] = d .

Обобщить на ndarray с помощью ellipsis

 np.einsum('ii...->i...',A)[:] =  d
  

Комментарии:

1. Но это все равно требует определения A заранее, я прав? Я надеялся найти что-то вроде A = some_magic_function(d, M) ?

2. @kMaster И выполнение инициализации A = np.zeros((M, M, N), dtype=d.dtype) вас беспокоит?

3. Да, в основном потому, что это означает, что мы выделяем M*M*N элемент памяти для этого массива, тогда N как для хранения такого массива должно быть достаточно только элементов.

4. @kMaster Вы, вероятно, хотите сохранить в разреженной матрице? К сожалению, нет ни одного для 3D или выше.