こしあん
2018-10-28

Numpyの配列をN個飛ばしで列挙する簡単な方法


41.8k{icon} {views}


Numpyの配列から奇数番目、偶数番目の要素を取り出したいときが稀によくあります。インデックスの配列を定義する必要があるのかなと思いますが、とても簡単な方法があります。それを見ていきましょう。

基本は「::スキップしたい間隔」

例として、0~9までの配列をとります。

>>> a=np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

これをN個飛ばしで抽出したいときは「::N」とスライスのが基本です。

偶数番目だけ抽出

まず偶数番目だけ抽出してみます。

>>> a[::2]
array([0, 2, 4, 6, 8])

0, 2, 4, ……と偶数番目の要素が取り出せましたね。

奇数番目を抽出

次に奇数番目の取り出し方です。開始インデックスを指定しましょう。

>>> a[1::2]
array([1, 3, 5, 7, 9])

開始インデックスを1にすることで、同じ2間隔の抽出ながら奇数番目を取り出すことができました。

2以上の偶数を抽出

開始インデックスを指定できるのなら、「○以上の偶数」という抽出の仕方もできます。

>>> a[2::2]
array([2, 4, 6, 8])

6未満の偶数を抽出

開始インデックスを指定できるのなら終了インデックスも指定できるはずです。もちろんできます。しかし、境界値判定は「未満」であることに注意してください。これは普通のNumpyのスライスのときと同じです。

>>> a[:6:2]
array([0, 2, 4])

5未満の奇数を抽出

今までの合わせ技です。5未満の奇数を抽出してみましょう。

>>> a[1:5:2]
array([1, 3])

全て抽出前のインデックス基準に判定していることに注意しましょう。

4以上8未満の偶数を抽出

偶数の場合は開始インデックスを指定しなくてもよかったですが、明示的に指定することもできます。

>>> a[4:8:2]
array([4, 6])

要するに奇数が出るか偶数が出るかというのは、開始インデックスによりけりなので、命令的には「2個飛ばしで出せ」ということにすぎないというのがわかるでしょう。

反転スライスの「::-1」とのゆるい関係

さてご存知の方も多いとは思いますが、Numpyでは「::-1」で反転スライスができます。

>>> a[::-1]
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])

実はこれとの合わせ技もできます。見ていきましょう。

反転して奇数のみ抽出

「::-1」だと反転になるけど、「::-2」ならどうなるだろう?という点です。この場合は反転した奇数が出てきます。

>>> a[::-2]
array([9, 7, 5, 3, 1])

反転した偶数のみ抽出

じゃあ反転した偶数ってどうやるの?ってことなんですが、開始インデックスを「8」として指定します。

>>> a[8::-2]
array([8, 6, 4, 2, 0])

開始インデックスはスライス前のインデックスであるため、反転する場合は大きい方のインデックスを指定してあげないといけません。なので、反転済みのインデックスを入ればいいやと考えて次のようにするのは想定しない挙動を招きます。

>>> a[0::-2]
array([0])
>>> a[1::-2]
array([1])

反転した4より大きく8以下の偶数を抽出

もちろん終了インデックスも指定できます。ただ、境界値判定が変わることに注意してください。反転しない場合は「A以上B未満」でしたが、反転すると「Aより大きくB以下」に変わります。

>>> a[8:4:-2]
array([8, 6])

これを4以上8未満の偶数+反転としたい場合は、一例ですがスライスを2段階に分けるのがよいと思います。

>>> a[4:8:2][::-1]
array([6, 4])

違いをよく味わってください。



Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です