条件を指定して配列の要素を選択するにはどうすればよいですか?


156

私はnumpyの配列を持っていると仮定しx = [5, 2, 3, 1, 4, 5]y = ['f', 'o', 'o', 'b', 'a', 'r']。で1 より大きく5より小さい要素にy対応する要素を選択したいx

私は試した

x = array([5, 2, 3, 1, 4, 5])
y = array(['f','o','o','b','a','r'])
output = y[x > 1 & x < 5] # desired output is ['o','o','a']

しかし、これは機能しません。どうすればいいですか?

回答:


220

括弧を追加すると、式が機能します。

>>> y[(1 < x) & (x < 5)]
array(['o', 'o', 'a'], 
      dtype='|S1')

1
それはいいです。vecMask = 1 <xは、vecMask =(False、True、...)のようなベクトルマスクを生成します。これは、他のベクトルマスクと組み合わせるだけです。各要素は、ソースベクトルの要素を取得するための条件(True)または取得しない(False)です。これは、フルバージョンのnumpy.extract(vecMask、vecSrc)、またはnumpy.where(vecMask、vecSrc、vecSrc2)でも使用できます。
MasterControlProgram

6
@JennyYueJin:優先順位が原因で発生します。(ビットごと)&<およびよりも優先順位が高く、さらに>(論理)よりも優先順位が高くなりandます。x > 1 and x < 5最初に不等式を評価し、次に論理結合を評価します。and(の値)x > 1 & x < 5のビット単位の結合を評価し、次に不等式を評価します。不等式が最初に評価されるように強制するため、すべての操作は意図した順序で行われ、結果はすべて明確に定義されています。こちらのドキュメントをご覧ください。1x(x > 1) & (x < 5)
calavicci

@ ru111 Python 3.6でも動作します(動作を停止する理由はありません)。
jfs

「ValueError:複数の要素を持つ配列の真理値があいまいです。a.any()またはa.all()を使用してください」
ru111

@ ru111を記述する必要があります(0 < x) & (x < 10)(回答に示されているように)。代わり0 < x < 10に、Pythonのどのバージョンのnumpy配列でも機能しません。
jfs

34

IMO OPは実際にはnp.bitwise_and()(別名&は必要ありませんがnp.logical_and()Trueand などの論理値を比較しているため、実際に必要です。違いを確認するには、論理対ビットごとのFalseこのSOの投稿を参照してください。

>>> x = array([5, 2, 3, 1, 4, 5])
>>> y = array(['f','o','o','b','a','r'])
>>> output = y[np.logical_and(x > 1, x < 5)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
      dtype='|S1')

これを行う同等の方法はnp.all()axis引数を適切に設定することです。

>>> output = y[np.all([x > 1, x < 5], axis=0)] # desired output is ['o','o','a']
>>> output
array(['o', 'o', 'a'],
      dtype='|S1')

数字で:

>>> %timeit (a < b) & (b < c)
The slowest run took 32.97 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 1.15 µs per loop

>>> %timeit np.logical_and(a < b, b < c)
The slowest run took 32.59 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 1.17 µs per loop

>>> %timeit np.all([a < b, b < c], 0)
The slowest run took 67.47 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 5.06 µs per loop

その使用はnp.all()遅いですが、&logical_andほぼ同じです。


7
評価の対象について話す方法については、少し注意する必要があります。例えば、でoutput = y[np.logical_and(x > 1, x < 5)]x < 5 されている評価関数の外起こるので、それは、第二引数のにもかかわらず、(おそらく莫大なアレイを作成する)を評価。IOW、logical_and2つの評価済みの引数が渡されます。これは通常の場合とは異なりa and bいる、bあれば評価されないatruelikeです。
DSM

15
ブール配列のbitwise_and()とlogical_and()の間に違いはありません
jfs

21

@JF Sebastianと@Mark Mikofskiの回答に1つの詳細を追加し
ます。(配列の実際の値ではなく)対応するインデックスを取得したい場合は、次のコードを実行します。

複数(すべて)の条件を満たす場合:

select_indices = np.where( np.logical_and( x > 1, x < 5) )[0] #   1 < x <5

複数の(または)条件を満たす場合:

select_indices = np.where( np.logical_or( x < 1, x > 5 ) )[0] # x <1 or x >5

2
numpy.whereはインデックスの配列を返すだけでなく、代わりに配列を含むタプル(condition.nonzero()の出力)を返すことに注意してください。この場合は(the array of indices you want,)、必要なselect_indices = np.where(...)[0]結果を取得する必要があります。そして期待しています。
calavicci

5

np.vectorizeはそのような仕事に使うのが好きです。以下を検討してください。

>>> # Arrays
>>> x = np.array([5, 2, 3, 1, 4, 5])
>>> y = np.array(['f','o','o','b','a','r'])

>>> # Function containing the constraints
>>> func = np.vectorize(lambda t: t>1 and t<5)

>>> # Call function on x
>>> y[func(x)]
>>> array(['o', 'o', 'a'], dtype='<U1')

利点は、ベクトル化された関数にさらに多くのタイプの制約を追加できることです。

それが役に立てば幸い。


1
これはNumPyでインデックスを作成するための良い方法ではありません(非常に遅くなります)。
Alex Riley

1

実際に私はこのようにします:

L1は、条件1を満たす要素のインデックスリストです(多分somelist.index(condition1)またはnp.where(condition1)をしてL1を取得)。

同様に、条件2を満たす要素のリストであるL2を取得します。

次に、次を使用して交差点を見つけます intersect(L1,L2)

複数の条件を満たす条件を満たす場合は、複数のリストの共通部分を見つけることもできます。

次に、xなどの他の配列にインデックスを適用できます。


0

2D配列の場合、これを行うことができます。条件を使用して2Dマスクを作成します。配列に応じて、条件マスクをintまたはfloatに型キャストし、元の配列と乗算します。

In [8]: arr
Out[8]: 
array([[ 1.,  2.,  3.,  4.,  5.],
       [ 6.,  7.,  8.,  9., 10.]])

In [9]: arr*(arr % 2 == 0).astype(np.int) 
Out[9]: 
array([[ 0.,  2.,  0.,  4.,  0.],
       [ 6.,  0.,  8.,  0., 10.]])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.