Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python numpy将二维矩阵重塑为无环对称矩阵阵列(三维阵列)_Python_Numpy - Fatal编程技术网

Python numpy将二维矩阵重塑为无环对称矩阵阵列(三维阵列)

Python numpy将二维矩阵重塑为无环对称矩阵阵列(三维阵列),python,numpy,Python,Numpy,假设我有一个如下形式的2D数组 D = [ [A11,A21,A31,A22,A23,A33], [B11,B21,B31,B22,B23,B33], [C11,C21,C31,C22,C23,C33] ] 其中每个D[i]都是对称矩阵的表示 对称矩阵的形状可以如下所示: [ [[A11,A21,A31 A21,A22,A23 A31,A23,A33]], [[B11,B21,B31 B21,B22,B23 B31,B23,B33]], [[C11,C2

假设我有一个如下形式的2D数组

D = [
 [A11,A21,A31,A22,A23,A33],
 [B11,B21,B31,B22,B23,B33],
 [C11,C21,C31,C22,C23,C33]
]
其中每个
D[i]
都是对称矩阵的表示

对称矩阵的形状可以如下所示:

[
 [[A11,A21,A31
   A21,A22,A23
   A31,A23,A33]],

 [[B11,B21,B31
   B21,B22,B23
   B31,B23,B33]],

 [[C11,C21,C31
   C21,C22,C23
   C31,C23,C33]]
]
因此
D[i]
是第i个对称矩阵(带对角线)下三角部分的值列表

通过从
result=np.zero(3,3,3)
开始执行迭代循环很容易,然后我们填充条目

请注意,我不需要计算相关性等,因为协方差矩阵的值已经给出了。我只想在一定的约束条件下(对称和正确索引)将2D重塑为3D


我想知道是否有更有效的方法不使用循环?谢谢

如果我理解正确的话,我刚才也遇到过类似的问题。我看到了你的问题,决定用一个通解(适用于3维或更大的维度)再尝试一次。我找不到一种没有任何循环的方法(抱歉),但它非常简单,可以定义为一个以数组和维度为参数的函数

解决方案 下面是我用来从一个数组中生成您所要求的类型的矩阵的代码(注意,我刚刚删除了字母,并使用int进行演示)。它仍然使用嵌套循环

import numpy as np

D = [
 [11,21,31,22,23,33],
 [11,21,31,22,23,33],
 [11,21,31,22,23,33]
]

d = 3 # dimension
N = 3 # number of sets (A, B, C) or len(D)

# index offset matrix to index from D
offsets = np.zeros((d, d), dtype=int)

# adjustments to offset matrix at each i,j index
adj = np.arange(d-2, 0, -1)
for i in range(1, d-1):
    offsets[i:, i:] += adj[i-1]

cov = np.empty((N, d, d), dtype=int)

# iterate over A, B, C
for n in range(N):
    for i in range(d):
        for j in range(d):
            cov[n, i, j] = D[n][i+j+offsets[i, j]]

print(cov)
这张照片

[[[11 21 31]
  [21 22 23]
  [31 23 33]]

 [[11 21 31]
  [21 22 23]
  [31 23 33]]

 [[11 21 31]
  [21 22 23]
  [31 23 33]]]
如果你有一个更大的集合:

D = [
 [11, 21, 31, 41, 51, 61, 22, 23, 24, 25, 26, 33, 34, 35, 36, 44, 45, 46, 55, 56, 66],
 [11, 21, 31, 41, 51, 61, 22, 23, 24, 25, 26, 33, 34, 35, 36, 44, 45, 46, 55, 56, 66],
 [11, 21, 31, 41, 51, 61, 22, 23, 24, 25, 26, 33, 34, 35, 36, 44, 45, 46, 55, 56, 66]
]

d = 6
N = 3
offsets = np.zeros((d, d), dtype=int)
adj = np.arange(d-2, 0, -1)
for i in range(1, d-1):
    offsets[i:, i:] += adj[i-1]

cov = np.empty((N, d, d), dtype=int)
for n in range(N):
    for i in range(d):
        for j in range(d):
            cov[n, i, j] = D[n][i+j+offsets[i, j]]

print(cov)
你会得到:

[[[11 21 31 41 51 61]
  [21 22 23 24 25 26]
  [31 23 33 34 35 36]
  [41 24 34 44 45 46]
  [51 25 35 45 55 56]
  [61 26 36 46 56 66]]

 [[11 21 31 41 51 61]
  [21 22 23 24 25 26]
  [31 23 33 34 35 36]
  [41 24 34 44 45 46]
  [51 25 35 45 55 56]
  [61 26 36 46 56 66]]

 [[11 21 31 41 51 61]
  [21 22 23 24 25 26]
  [31 23 33 34 35 36]
  [41 24 34 44 45 46]
  [51 25 35 45 55 56]
  [61 26 36 46 56 66]]]
注释 这需要您的输入数组遵循该模式

A11, A12, A13, A14, A22, A23, A24, A33, A34, A44
就像你的三维问题一样

我通过将D中的指数映射到所需的矩阵上找到了这个解决方案,并发现它们是矩阵指数加上以下子矩阵的一些偏移:

# [[i+j,  i+j,   i+j,   i+j,   i+j ],
#  [i+j, i+j+3, i+j+3, i+j+3, i+j+3],
#  [i+j, i+j+3, i+j+5, i+j+5, i+j+5],
#  [i+j, i+j+3, i+j+5, i+j+6, i+j+6],
#  [i+j, i+j+3, i+j+5, i+j+6, i+j+6]]
这些偏移从0开始,然后随着i,j的增加,它们分别增加3,2,1。这种模式具有更高的维度

答案很长,但我希望能有所帮助,我以前肯定见过并遇到过这个问题


干杯

您可以通过3个步骤实现这一点(为了简单起见,从一个对称矩阵开始):

假设存在单个向量d0=D[0]

d0 = D[0]  # [A11,A21,A31,A22,A23,A33]
首先创建一个空矩阵

r = np.zeros([3, 3])  # note: any size will do
将d0分配到矩阵的上部

upper_tri = ~np.tri(3, 3, -1, dtype=bool)
# [[ True,  True,  True],
#  [False,  True,  True],
#  [False, False,  True]]

r[upper_tri] = d0
# [[A11,A21,A31],
#  [ 0 ,A22,A23],
#  [ 0 , 0 ,A33]]
然后转置结果并将其分配给自身,但应用仅与下部三角形匹配的遮罩:

lower_tri = ~upper_tri
r[lower_tri] = r.T[lower_tri]
# [[A11,A21,A31
#   A21,A22,A23
#   A31,A23,A33]]

您可以使用广播来扩展此方法,但这相当棘手。您需要转换每个输入和输出矩阵。这是因为适用于标量的方法(例如,这里A21是单个标量)也适用于向量

d0 = D.T  # [ [A11, B11, C11], [A21, B21, C21], [A31, B31, C31]... ]

N = 3  # as batch size to avoid confusion
r = np.zeros([3, 3, N])

upper_tri = ~np.tri(3, 3, -1, dtype=bool)  # same as before
r[upper_tri] = d0

lower_tri = ~upper_tri
r[lower_tri] = r.transpose([1, 0, 2])[lower_tri]

r = r.transpose([2, 0, 1])

有一组
tri
函数用于映射上部或下部三角形;感谢您的详细解决方案;事实证明,您可以非常有效地避免嵌套循环;请参阅公认的解决方案。希望这也能对你的项目有所帮助!这是一个很好的解决方案