查找具有唯一列的数组中每一行的最小值
Posted
技术标签:
【中文标题】查找具有唯一列的数组中每一行的最小值【英文标题】:Find minimum for every row in array with unique columns 【发布时间】:2021-10-13 13:47:43 【问题描述】:我需要在数组中找到按行的最小值,其中每个最小值必须来自唯一的列。
np.min(arr, axis=1)
提供逐行最小值,但可能多次包含同一列。
例如,给定:
a = np.array([
[4, 5, 6],
[1, 2, 3],
[7, 8, 9]
])
np.min(a, axis=1)
将输出:[4, 1, 7]
所有返回的最小值都来自第一列,但由于每列只能使用一次的约束,所需的输出将是 [5, 1, 9]
作为最佳分配:
1 是本示例中的最小值,因此分配给第一列。 5 是可以分配给第二列的最佳最小值(因为第二行已被使用)。
我现在唯一的想法是使用某种递归来实现这一点(这很可能非常耗时,对吧?)。
【问题讨论】:
为什么期望的输出不是[4, 2, 9]
,或[6, 1, 8]
,或[5, 3, 7]
?
那些不是最佳分配。例如。 1 是此示例中的最小值,因此分配给第一列(而不是 2 或 3)。 5 是可以分配给第二列的最佳最小值(因为第二行已被使用)。
你的数组有多大(元素数量)?
平均约为 400x400,很少达到 2000x2000
我仍然不完全清楚问题陈述。我知道(1)你想要一个包含每行最小值的数组,除了每列只能使用一次; (2) 目标是找到最小的解决方案; (3) 您通过选择网格中的最小值来描述选择第一个数字(“首先在第一行中选择 1
,因为 1
是网格中的最小值 [...]”)。但是输入[[4, 5, 6],[1, 2, 3],[7, 101, 100]]
呢?如果您总是在网格中选择最小的数字,您最终会得到[5,1,100]
的解,但答案[2,6,7]
的总和更小。
【参考方案1】:
您正在寻找的似乎是 N 个最小值,其中每个值的行和列索引都是唯一的(假设是 NxN 矩阵)。如果我们用它的初始坐标标记矩阵中的每个值,我们可以重新排列它们而不会失去判断它们来自哪里的能力。我不确定在numpy
中是否有一种使用自定义键进行排序的巧妙方法,所以这是一个不需要递归或回溯的普通 Python 解决方案:
def idx_matrix(matrix):
# return 1-D array of matrix values in (row_idx, col_idx, val) format
return [(r, c, val) for r, row in enumerate(matrix)
for c, val in enumerate(row)]
def find_minima(indexed_vals, limit=0):
# return array of indexed matrix values whose row and col indexes are unique
minima = []
rows = set()
cols = set()
for row, col, val in indexed_vals:
if row not in rows and col not in cols:
minima.append((row, col, val))
if limit and len(minima) == limit:
# optional optimization if you want to break off early
# after you've found a value for every row
break
rows.add(row)
cols.add(col)
return minima
def sort_by_val(indexed_vals):
# return indexed_vals sorted by original matrix value
return sorted(indexed_vals, key=lambda x: x[2])
def sort_by_row(indexed_vals):
# return indexed_vals sorted by row index
return sorted(indexed_vals, key=lambda x: x[0])
def strip_indices(indexed_vals):
# return a 1-D array with row and col index removed
return [v[2] for v in indexed_vals]
def find_minima_by_row(matrix):
# put it all together
indexed = idx_matrix(matrix)
indexed = sort_by_val(indexed)
minima = find_minima(indexed)
minima = sort_by_row(minima)
return strip_indices(minima)
matrix = [[4, 5, 6],
[1, 2, 3],
[7, 8, 9]]
results = find_minima_by_row(matrix)
print(f'results=')
matrix = [[20, 17, 5, 13, 19],
[11, 22, 8, 4, 9],
[ 0, 10, 2, 16, 23],
[ 1, 24, 21, 15, 14],
[ 3, 12, 6, 7, 18]]
results = find_minima_by_row(matrix)
print(f'results=')
results=[5, 1, 9]
results=[5, 4, 0, 14, 12]
这在我的工作站上使用 2000x2000 矩阵在大约 4 秒内运行。你可以在适当的地方做一些更节省空间的事情。
如果输入中有重复的值,我也看不出为什么这不起作用。
【讨论】:
【参考方案2】:如果您知道数组值的上限,则使用 numpy 执行上述操作的更简单方法(可能不会更快):
# matrix is a numpy 2-D array, k is some arbirtary large value
mapping = [None]*matrix.shape[0] # row-column mapping for minimum value
tmp = matrix.copy()
for i in range(matrix.shape[0]):
u, v = divmod(tmp.argmin(), tmp.shape[1])
mapping[u]=v
tmp[u,:]=k
tmp[:,v]=k
【讨论】:
以上是关于查找具有唯一列的数组中每一行的最小值的主要内容,如果未能解决你的问题,请参考以下文章