我有一个np.ndarray如下:
[(0,1,1),(0,4,1),(3,4,1),(0,3,2)]
有没有办法获得该nd数组中m个最小项的索引和值?所以,如果我想要4个最小的那个就是
{{1}}
其中(row,col,val)是上面的符号。
如果有多个值,则只需随机选择其中一个值。例如,有3个,然后下一个最小值是2,但(0,3,2),(1,2,2),(1,4,2)都是可能的选择。
基本上,我能否有效地从上三角矩阵中提取该格式的k个最小值(矩阵比上面的例子大得多)。我尝试使用方形,最小的方法展平它,但是我很难将索引和值对齐。谢谢!
答案 0 :(得分:2)
对于Inf
填充的数组 -
r,c = np.unravel_index(a.ravel().argsort()[:4], a.shape)
out = zip(r,c,a[r,c])
为了提高性能,请考虑使用np.argpartition
。因此,请将a.ravel().argsort()[:4]
替换为np.argpartition(a.ravel(), range(4))[:4]
。
示例运行 -
In [285]: a
Out[285]:
array([[ inf, 1., 3., 2., 1.],
[ inf, inf, 2., 3., 2.],
[ inf, inf, inf, 5., 4.],
[ inf, inf, inf, inf, 1.],
[ inf, inf, inf, inf, inf]])
In [286]: out
Out[286]: [(0, 1, 1.0), (0, 4, 1.0), (3, 4, 1.0), (0, 3, 2.0)]
对于一般情况 -
R,C = np.triu_indices(a.shape[1],1)
idx = a[R,C].argsort()[:4]
r,c = R[idx], C[idx]
out = zip(r,c,a[r,c])
示例运行 -
In [351]: a
Out[351]:
array([[ 68., 67., 81., 23., 16.],
[ 84., 83., 20., 66., 48.],
[ 58., 72., 98., 63., 30.],
[ 61., 40., 1., 86., 22.],
[ 29., 95., 38., 22., 95.]])
In [352]: out
Out[352]: [(0, 4, 16.0), (1, 2, 20.0), (3, 4, 22.0), (0, 3, 23.0)]
为了提高性能,请考虑使用np.argpartition
。因此,请将a[R,C].argsort()[:4]
替换为np.argpartition(a[R,C], range(4))[:4]
。
答案 1 :(得分:0)
这样的工作:
import numpy as np
a = np.random.rand(4,4)
tuples = [(ix,iy, a[ix,iy]) for ix, row in enumerate(a) for iy, i in enumerate(row)]
sorted(tuples,key=lambda x: x[2])[:10]
你问题中k = 10([:10]
)。
如果您只想要上三角形元素,可以在列表推导中添加条件:
a = np.random.rand(4,4)
tuples = [(ix,iy, a[ix,iy]) for ix, row in enumerate(a) for iy, i in enumerate(row) if ix<=iy]
sorted(tuples,key=lambda x: x[2])
答案 2 :(得分:0)
如果我的 np.array()是 n ,我可以通过展平它(使用* np.ndenumerate())并使用它来获取n个最小值 heapq 模块的 .heapify()和 .smallest()方法如下:
#!python
flattened = [(y,x) for x,y in np.ndenumerate(n)]
# tuples reversed for natural sorting on values rather than co-ords
heapq.heapify(flattened)
results = heapq.nsmallest(4, flattened)
但是这将使用大量额外的内存,并将Numpy高效数组中的数据和坐标提取到Python的本机列表中。因此,可能有更好的方法在Python中更原生地完成它。