我有一个 1d np.array。它的长度可能会根据用户输入而变化,但它始终保持单一维度。 请告知是否有从中创建对称二维 np.array 的有效方法? “对称”是指它的元素将遵循规则 k[i, j] = k[j, i]。
我意识到可以使用 python for 循环和 list 来完成,但那是非常低效的。
非常感谢!
示例: 例如,我们有 x = np.array([1, 2, 3])。想要的结果应该是
M = np.array([[1, 2, 3],
[2, 1, 2],
[3, 2, 1])
请您参考如下方法:
解释 #1
似乎您在每一行重复使用元素。因此,有了这种想法,一个使用 broadcasting 的实现会是——
def symmetricize(arr1D):
ID = np.arange(arr1D.size)
return arr1D[np.abs(ID - ID[:,None])]
sample 运行-
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]])
解释 #2
当您想将输入 1D 数组中的元素分配到对称 2D 数组时,我有另一种解释无需重复使用 ,这样我们就可以填充上三角部分一次,然后通过保持行和列索引之间的对称性来复制下三角区域的那些。因此,它只适用于特定大小的它。因此,作为预处理步骤,我们需要执行错误检查。在我们通过错误检查之后,我们将初始化一个输出数组并使用 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
sample 运行-
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]])
