numpy.arrayやリストで以上以下を条件指定し配列を取り出す [python]

結論

配列[(配列>=数) & (配列<=数)]

を使う

やりたいこと

例えば、

l = np.array([0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1,0])

があったとき、3以上7未満のように、複数条件で要素を取り出したい。

l = np.array([0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1,0])
# l2 = 何らかの動作
print(l2)  # => [3 4 5 6 6 5 4 3]

方法

上の例のようにリストlから3以上7未満の要素を取り出したい場合:

l[(l >= 3) & (l < 7)]  # => [3 4 5 6 6 5 4 3]

説明

何も考えず

l[3<=l<7]

とやると、

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-194-aa9d3443d177> in <module>
----> 1 l[3<=l<7]

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

だったり

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

のように帰ってくる。

これは、3<=l<7の部分が、「3以上かつ7以下の部分」を取ってきてほしいのか、「3以上または7以下の部分」を取ってきてほしいのか混乱してしまっているためにエラーが起きる

この問題を解決するために、まず2つの条件を&でまとめ、TrueとFalseだけの配列を作る↓

[(l >= 3) & (l < 7)]
 # => array([False, False, False,  True,  True,  True,  True, False, False,
       False, False, False,  True,  True,  True,  True, False, False,
       False])

つぎに、これを元々の配列lに当てはめ、必要な結果を得る

l[(l >= 3) & (l < 7)]
# => [3 4 5 6 6 5 4 3]

※ np.allを使ってもうまく行かない例↓

np.all(l, ((l >= 3) & (l < 7)))
# => TypeError: only integer scalar arrays can be converted to a scalar index