问题描述
对于我拥有的一组矩阵,称为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)
请注意,nanargmin
是a 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)