ndarrayでは配列に対してのデータ処理を、ループ文を書くことなく、簡単かつ高速に行うことができ、この演算方法をベクトル演算という。

今回紹介するのはPythonで用意されている三項演算子(条件制御文)を、ベクトル演算で使う場合の表現方法だ。

通常の三項演算子

まずはPython通常の三項演算子から見てみよう。

x  = True

y = "a" if x else "b"
# Trueの場合 if 条件式 else Falseの場合

主に条件によって代入する値を変えたいときに三項演算子は使える。

単純な代入処理なら、複数行にわたるif文を1行で簡潔に書ける三項演算子を使った方が良いだろう。

ndarrayで三項演算子を使う方法

次にndarrayで三項演算子を使う例を見ていく。

Python標準の三項演算子

まずは単純にPython標準機能を使った例だ。

import numpy as np

x_arr = np.array([1.1, 1.2, 1.3])
y_arr = np.array([2.1, 2.2, 2.3])
cond = np.array([True, False, False])

result = [(x if c else y) for x, y, c in zip(x_arr, y_arr, cond)]

result # [1.1, 2.2, 2.3]

x_arr、y_arrにそれぞれ三つの要素を定義する。

condの条件がTrueの場合はx_arrの値を、Falseの場合はy_arrの値をresultに格納している。

ただしこれは、7行目のPythonリスト内包表記が複雑になる上、多次元配列に対応できないなど、様々な問題が考えられる。

NumPyのwhere関数を使う例

where関数は三項演算子のベクトル演算版で、先述した問題を全て解決してくれる。

まずは一次元配列を処理する例を見てみよう。

import numpy as np

x_arr = np.array([1.1, 1.2, 1.3])
y_arr = np.array([2.1, 2.2, 2.3])
cond = np.array([True, False, False])

result = np.where(cond, x_arr, y_arr)
result # array([1.1, 2.2, 2.3])

どうだろう。
同じ結果を得ることができたが、一目瞭然でコードが簡潔になったことが分かったはずだ。

where関数の第一引数には条件となる配列を入れるが、第二引数、第三引数は配列でなくスカラー値を入れることもできる。

多次元配列を処理する例と組み合わせて見てみよう。

import numpy as np

arr = np.random.randn(5, 5)

result = np.where(arr > 0, 1, -1)
result
# array([[ 1,  1, -1,  1, -1],
#        [-1, -1,  1, -1,  1],
#        [ 1, -1,  1, -1,  1],
#        [ 1, -1, -1, -1, -1],
#        [ 1,  1,  1,  1,  1]])

5×5の二次元配列arrに乱数を設定し、乱数が0以上の場合は1を、そうでない場合は-1をresult配列に代入する例だ。

このように、ある配列をベースに新しい配列を生成する際に活用することができる。