在成对比较 NxN numpy 数组中找到 N 个最小值?

Find the N smallest values in a pair-wise comparison NxN numpy array?

我有一个 python NxN numpy 双精度成对数组(矩阵)。例如 (i,j) 的每个数组元素是 ij项。 i==j 的对角线为 1,因为它是对自身的成对测量。这也意味着 2D NxN numpy 数组可以用矩阵三角形形式表示(numpy 数组的一半与对角线上的另一半相同)。

截断表示:

[[1.         0.11428571 0.04615385 ... 0.13888889 0.07954545 0.05494505]
 [0.11428571 1.         0.09836066 ... 0.06578947 0.09302326 0.07954545]
 [0.04615385 0.09836066 1.         ... 0.07843137 0.09821429 0.11711712]
 ...
 [0.13888889 0.06578947 0.07843137 ... 1.         0.34313725 0.31428571]
 [0.07954545 0.09302326 0.09821429 ... 0.34313725 1.         0.64130435]
 [0.05494505 0.07954545 0.11711712 ... 0.31428571 0.64130435 1.        ]]

我想得到最小的 N 个值,同时不包括成对的值两次,因为成对的重复会导致这种情况,例如,(5,6 ) == (6,5),并且我不想包含 1 的任何相同对角线值,其中 i == j

我知道 numpy 有 partition 方法,我已经看到很多平面数组的例子,但我正在努力寻找任何简单的成对方法比较矩阵。

编辑#1 根据我下面的第一反应,我实施了:

seventyPercentInt: int = round((populationSizeInt/100)*70)

upperTriangleArray = dataArray[np.triu_indices(len(dataArray),1)]
seventyPercentArray = upperTriangleArray[np.argpartition(upperTriangleArray,seventyPercentInt)][0:seventyPercentInt]

print(len(np.unique(seventyPercentArray)))

upperTriangleArray numpy 数组有 1133265 个元素可供选择最低的 k。在这种情况下,kseventyPercentInt 表示,大约有 1054 个值。但是,当我应用 np.argpartition 时,仅返回 0 的值。

平面数组upperTriangleArray缩小为形状(1133265,)。

解决方案

根据下面的第一个回复(接受的答案),我的代码有效:

upperTriangleArray = dataArray[np.triu_indices(len(dataArray),1)]

seventyPercentInt: int = round((len(upperTriangleArray)/100)*70)

seventyPercentArray = upperTriangleArray[np.argpartition(upperTriangleArray,seventyPercentInt)][0:seventyPercentInt]

我 运行 使用 seventyPercentInt 遇到了一些小麻烦(我自己造成的)。我没有取 70% 的成对元素,而是取了 70% 的元素进行比较。两个截然不同的值。

您可以使用np.triu_indices只保留上三角的值。

然后您可以使用np.argpartition,如下例所示。

import numpy as np

A = np.array([[1.0, 0.1, 0.2, 0.3],
            [0.1, 1.0, 0.4, 0.5],
            [0.2, 0.3, 1.0, 0.6],
            [0.3, 0.5, 0.4, 1.0]])

A_upper_triangle = A[np.triu_indices(len(A), 1)]

print(A_upper_triangle)
# return [0.1 0.2 0.3 0.3 0.5 0.4]

k=2

print(A_upper_triangle[np.argpartition(A_upper_triangle, k)][0:k])
#return [0.1 0.2]