从N维数组中的值构造(N + 1)维对角矩阵

时间:2018-02-05 16:33:27

标签: python arrays numpy multidimensional-array diagonal

我有一个N维数组。我想通过将最终尺寸的值放在对角线上,将其扩展为(N + 1)维数组。

例如,使用显式循环:

In [197]: M = arange(5*3).reshape(5, 3)

In [198]: numpy.dstack([numpy.diag(M[i, :]) for i in range(M.shape[0])]).T
Out[198]: 
array([[[ 0,  0,  0],
        [ 0,  1,  0],
        [ 0,  0,  2]],

       [[ 3,  0,  0],
        [ 0,  4,  0],
        [ 0,  0,  5]],

       [[ 6,  0,  0],
        [ 0,  7,  0],
        [ 0,  0,  8]],

       [[ 9,  0,  0],
        [ 0, 10,  0],
        [ 0,  0, 11]],

       [[12,  0,  0],
        [ 0, 13,  0],
        [ 0,  0, 14]]])

是5×3×3阵列。

我的实际数组很大,我想避免显式循环(隐藏map中的循环而不是列表理解没有性能增益;它仍然是一个循环)。虽然numpy.diag用于构造规则的二维对角矩阵,但它不会扩展到更高的维度(当给定二维数组时,它将提取其对角线)。 numpy.diagflat返回的数组使一切成为一个大的对角线,产生一个15×15的数组,其中有更多的零,无法重新形成5×3×3。

有没有办法从N维数组中的值有效地构造(N + 1) - 对角矩阵,而无需多次调用diag

3 个答案:

答案 0 :(得分:3)

使用numpy.diagonal查看正确形状的N + 1维数组的相关对角线,强制视图可以用setflags写入,并写入视图:

expanded = numpy.zeros(M.shape + M.shape[-1:], dtype=M.dtype)

diagonals = numpy.diagonal(expanded, axis1=-2, axis2=-1)
diagonals.setflags(write=True)

diagonals[:] = M

这会将您想要的数组生成为expanded

答案 1 :(得分:3)

你可以使用普遍存在的np.einsum几乎不可能猜到的你不知道的功能。如下使用einsum将返回广义对角线的可写视图:

>>> import numpy as np
>>> M = np.arange(5*3).reshape(5, 3)
>>> 
>>> out = np.zeros((*M.shape, M.shape[-1]), M.dtype)
>>> np.einsum('...jj->...j', out)[...] = M
>>> out
array([[[ 0,  0,  0],
        [ 0,  1,  0],
        [ 0,  0,  2]],

       [[ 3,  0,  0],
        [ 0,  4,  0],
        [ 0,  0,  5]],

       [[ 6,  0,  0],
        [ 0,  7,  0],
        [ 0,  0,  8]],

       [[ 9,  0,  0],
        [ 0, 10,  0],
        [ 0,  0, 11]],

       [[12,  0,  0],
        [ 0, 13,  0],
        [ 0,  0, 14]]])

答案 2 :(得分:0)

将N-D数组的最后一个维度转换为对角矩阵的一般方法:

我们需要减少数组的维数,将numpy.diag()函数应用于每个向量,然后将其重建为原始维度+ 1.

将矩阵重塑为二维:

M.reshape(-1, M.shape[-1])

然后使用mapnp.diag应用于该值,并使用以下内容重建具有附加维度的矩阵:

result.reshape([*M.shape, M.shape[-1]])

所有这些结合起来给出了以下内容:

result = np.array(list(map(
   np.diag,
   M.reshape(-1, M.shape[-1])
))).reshape([*M.shape, M.shape[-1]])

一个例子:

shape = np.arange(2,8)
M = np.arange(shape.prod()).reshape(shape)
print(M.shape)  # (2, 3, 4, 5, 6, 7)

result = np.array(list(map(np.diag, M.reshape(-1, M.shape[-1])))).reshape([*M.shape, M.shape[-1]])

print(result.shape)  # (2, 3, 4, 5, 6, 7, 7)

res[0,0,0,0,2,:]包含以下内容:

array([[14,  0,  0,  0,  0,  0,  0],
       [ 0, 15,  0,  0,  0,  0,  0],
       [ 0,  0, 16,  0,  0,  0,  0],
       [ 0,  0,  0, 17,  0,  0,  0],
       [ 0,  0,  0,  0, 18,  0,  0],
       [ 0,  0,  0,  0,  0, 19,  0],
       [ 0,  0,  0,  0,  0,  0, 20]])