对2D numpy数组执行组操作

2024-06-11 00:22:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个2dnumpy数组(实际上是一个相似矩阵),我需要在这个数组上按块计算平均值。例如,使用以下矩阵:

sima = np.array([[1,0.8,0.7,0.3,0.1,0.5],
                 [0.8,1,0.1,0.5,0.2,0.5],
                 [0.7,0.1,1,0.1,0.3,0.9],
                 [0.3,0.5,0.1,1,0.8,0.5],
                 [0.1,0.2,0.3,0.8,1,0.5],
                 [0.5,0.5,0.9,0.5,0.5,1]])

标签和向量:

labels = np.array([1,1,1,2,2,3])

这意味着矩阵的前三行(以及列,因为相似性矩阵是对称的)对应于簇1,下两行对应于簇2,最后一行对应于簇3。你知道吗

我需要计算sima中与labels中的标签相对应的块的平均值。产生以下输出:

0.69 0.25 0.63 
0.25 0.90 0.50 
0.63 0.50 1.00

到目前为止,我有一个可行的解决方案,在标签和屏蔽数组上使用双循环:

labels_matrix = np.tile(np.array(labels), (len(labels), 1))
output = pd.DataFrame(np.zeros(shape = (3,3)))

for i in range(3):
  for j in range(3):
    mask = (labels_matrix != j+1) | (labels_matrix.T != i+1)
    output.loc[i,j] = np.mean(np.mean(np.ma.array(sima, mask = mask)))

这段代码产生正确的输出,但我的实际矩阵是50kx50k,这段代码需要永远计算。我怎样才能让它更快?你知道吗

注意:我需要一个不同的数量级的速度,所以我希望使用技巧,如相似矩阵的对称性将是不够的。你知道吗


Tags: inforoutputlabelsnprange矩阵mask
1条回答
网友
1楼 · 发布于 2024-06-11 00:22:59

对于排序标签,我们可以使用np.add.reduceat-

In [62]: idx = np.flatnonzero(np.r_[True,labels[:-1] != labels[1:],True])

In [63]: c = np.diff(idx)

In [64]: sums = np.add.reduceat(np.add.reduceat(sima,idx[:-1],axis=0),idx[:-1],axis=1)

In [65]: sums/(c[:,None]*c)
Out[65]: 
array([[0.68888889, 0.25      , 0.63333333],
       [0.25      , 0.9       , 0.5       ],
       [0.63333333, 0.5       , 1.        ]])

相关问题 更多 >