如何以最有效的方式从numpy 1D数组创建对称矩阵

Mik*_* T. 1 python arrays numpy matrix linear-algebra

我有一个1d np.array。其长度可能会根据用户输入而有所不同,但始终保持一维。请告知是否有一种有效的方法可以从中创建对称2d np.array?“对称”是指其元素将根据规则k [i,j] = k [j,i]。

我意识到可以使用python forloop和lists进行处理,但这效率很低。

提前谢谢了!

示例: 例如,我们有x = np.array([1, 2, 3])。理想的结果应该是

M = np.array([[1, 2, 3], 
              [2, 1, 2],
              [3, 2, 1])
Run Code Online (Sandbox Code Playgroud)

Div*_*kar 6

解释#1

似乎您正在每行重用元素。因此,有了这种想法,使用的实现broadcasting将是 -

def symmetricize(arr1D):
    ID = np.arange(arr1D.size)
    return arr1D[np.abs(ID - ID[:,None])]
Run Code Online (Sandbox Code Playgroud)

样品运行 -

In [170]: arr1D
Out[170]: array([59, 21, 70, 10, 42])

In [171]: symmetricize(arr1D)
Out[171]: 
array([[59, 21, 70, 10, 42],
       [21, 59, 21, 70, 10],
       [70, 21, 59, 21, 70],
       [10, 70, 21, 59, 21],
       [42, 10, 70, 21, 59]])
Run Code Online (Sandbox Code Playgroud)

解释#2

当你想将输入1D数组中的元素分配到一个对称2D数组中而不重复使用时,我有另一种解释,这样我们就可以填充上三角部分一次,然后通过保持下三角区域之间的对称性来复制它们行和列索引。因此,它只适用于它的特定大小。因此,作为预处理步骤,我们需要执行错误检查。在我们通过错误检查之后,我们将初始化一个输出数组并使用 a 的行和列索引按triangular array原样分配一次值,并使用交换索引一次分配另一个三角形部分的值,从而赋予它对称效果.

看起来Scipy's squareform应该能够完成这项任务,但是从文档来看,它似乎不支持用输入数组元素填充对角线元素。所以,让我们给我们的解决方案一个密切相关的名称。

因此,我们会有一个像这样的实现 -

def squareform_diagfill(arr1D):
    n = int(np.sqrt(arr1D.size*2))
    if (n*(n+1))//2!=arr1D.size:
        print "Size of 1D array not suitable for creating a symmetric 2D array!"
        return None
    else:
        R,C = np.triu_indices(n)
        out = np.zeros((n,n),dtype=arr1D.dtype)
        out[R,C] = arr1D
        out[C,R] = arr1D
    return out
Run Code Online (Sandbox Code Playgroud)

样品运行 -

In [179]: arr1D = np.random.randint(0,9,(12))

In [180]: squareform_diagfill(arr1D)
Size of 1D array not suitable for creating a symmetric 2D array!

In [181]: arr1D = np.random.randint(0,9,(10))

In [182]: arr1D
Out[182]: array([0, 4, 3, 6, 4, 1, 8, 6, 0, 5])

In [183]: squareform_diagfill(arr1D)
Out[183]: 
array([[0, 4, 3, 6],
       [4, 4, 1, 8],
       [3, 1, 6, 0],
       [6, 8, 0, 5]])
Run Code Online (Sandbox Code Playgroud)


kar*_*kfa 5

您正在寻找的是一种特殊的Toeplitz矩阵,并且易于使用scipy生成

from numpy import concatenate, zeros
from scipy.linalg import toeplitz

toeplitz([1,2,3])

array([[1, 2, 3],
       [2, 1, 2],
       [3, 2, 1]])
Run Code Online (Sandbox Code Playgroud)

另一个特殊的矩阵解释可以使用Hankel矩阵,它将为您提供给定数组的最小尺寸正方形矩阵。

from scipy.linalg import hankel

a=[1,2,3]

t=int(len(a)/2)+1
s=t-2+len(a)%2

hankel(a[:t],a[s:])

array([[1, 2],
       [2, 3]])
Run Code Online (Sandbox Code Playgroud)