2017-02-01 3 views
5

私はnp.ndarrayを持っていますそのnd配列?だから、もし私が4を最小にしたいのであれば、それは上の表記であるでしょう。メートル最小値は

[(0,1,1),(0,4,1),(3,4,1),(0,3,2)] 

ここで(行、col、val)は上記の表記です。

複数の値がある場合、そのうちの1つはランダムに選択されます。例えば、3つのものがあり、次に小さいものは値2であるが、(0,3,2)、(1,2,2)、(1,4,2)は全て可能な選択肢である。

本質的に、上の三角行列からその形式のk個の最小値を効率的に抽出できます(行列は上の例よりもはるかに大きい)。私は正方形のフォームnsmallestを使用してそれを平坦化しようとしましたが、インデックスと値を整列するのに問題があります。ありがとう!このような

+0

可能な複製http://stackoverflow.com/questions/30577375/have-numpy-argsort-return-an-array-of-2d-indices 'np.dstack(np.unravel_index(np.argsort(tri .ravel())、arr.shape)) ' 残っているのは値を圧縮しているだけです。 – 3novak

+0

これは助けになるかもしれません:http://stackoverflow.com/a/10337643/149076 ...それは最小ではなく、最大のK項目を見つけるのですが。 もう1つの方法は、numpy.ndenumerate()を使用してheapq.nsmallest()アイテムを取得する前にヒープに入る座標と値のフラットなリストを生成することです。 –

+0

投稿されたソリューションのいずれかがあなたのために機能しましたか? – Divakar

答えて

2

- パフォーマンスを実現するため

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]に置き換えてください。

サンプル実行 -

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 [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)] 

パフォーマンスのために

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]に置き換えてください。

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])あなたの質問からを。 Infいっぱいアレイの場合

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]) 
0

np.array()Nであれば、私は(()(np.ndenumerate *で)それを平坦化し、heapqモジュールの.heapifyを使用して、それから、n個の最小値を得ることができますそうのような)と.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) 

しかし、これは余分なメモリをたくさん使用し、Pythonのネイティブリストにnumpyのの効率的な配列のうち、データと座標を抽出します。だから、おそらくPythonでよりネイティブにそれを行うより良い方法があります。

+0

私はこれを試しましたが、行列が巨大なのでループのために実際には遅いです –

+0

まさに私が言ったように、私の他の提案、http://stackoverflow.com/a/6910715/149076 ...ボトルネックはコンパイルされた拡張です。部分ソートのためのNumpy。 –