如果最小值满足特定条件,则编写脚本以查找第二个最小值

问题描述

对于我拥有的一组矩阵,称为distance_matrix(它们存在于一个函数中,然后在给定范围内生成所有矩阵)。我需要在此矩阵中找到最小值,显然由索引对表示,对此我有以下代码

min_indices = np.unravel_index(np.argmin(np.abs(distance_matrix)),np.shape(distance_matrix))

这非常好用。但是现在我需要写一些东西,如果上面的代码返回的索引是(0,0),则找到第二个最小值。我猜我不能使用上面的代码,因为您不能修改它以查找下一个值(据我所知)。香港专业教育学院尝试了一个if循环,但那不是很有效:

sdiff = np.diff(np.sign(np.diff(distance_matrix)))
rising_1 = (sdiff == 2) 
rising_2 = (sdiff[:-1] == 1) & (sdiff[1:] == 1) 
rising_all = rising_1 
rising_all[1:] = rising_all[1:] | rising_2 
min_ind = np.where(rising_all)[0] + 1 
minima = list(zip(min_ind,distance_matrix[min_ind]))
for ind_pair in range(0,len(minima)):
    if ind_pair ==(0,0):
        minima=sorted(minima,key=lambda pair: pair[1])[1]
    else:
        minima=sorted(minima,key=lambda pair: pair[1])[0]

解决方法

假设距离矩阵是二维的,并使用以下测试数据:

distance_matrix = np.array([[0.,1.,2. ],[1.,0.5,1.5],[2.,1.5,2. ]])

现在

np.unravel_index(
  np.argmin(np.abs(distance_matrix)),np.shape(distance_matrix)
)

当然会为您返回(0,0),这是您不想要的。但是有没有一个原因不能使您无法通过使用以下命令来做到这一点:

mask = np.ones(np.shape(distance_matrix))
mask[0,0] = np.nan  # you can put this in a loop if there is
                     # more than one coordinate set you don't want

distance_matrix * mask
# array([[nan,#        [1.,#        [2.,2. ]])

np.unravel_index(
  np.nanargmin(np.abs(distance_matrix * mask)),np.shape(distance_matrix)
)
# (1,1)

请注意,nanargmina version of argmin,它会忽略NaN s。

,

您可以使用np.argpartition一次找到前两个最小元素的索引。对数组的第二个元素进行分区可确保第一个元素变小,因此您可以同时获得这两个元素。

indices2 = np.unravel_index(
        np.argpartition(np.abs(distance_matrix),1,None),distance_matrix.shape)

您必须传递axis中的None才能遍历索引,而不是对列进行分区。否则,您将无法直接在结果上调用np.unravel_index

如果您要分别分配每个索引:

i = np.argpartition(np.abs(distance_matrix),None)
indices = np.unravel_index(i[0],distance_matrix.shape)
indices2 = np.unravel_index(i[1],distance_matrix.shape)

如果要获得更多的最小值,则必须sort数组的左侧。

k = 5
i = np.argpartition(np.abs(distance_matrix),k,None)[:k]
i.sort()
indices = np.unravel_index(i,distance_matrix.shape)