DataFrameからの条件抽出の方法は以前以下の記事でまとめましたのでこちらを参照してください。

PandasのDataFrameの条件抽出の方法まとめ /features/pandas-cond-extraction.html

Pandasのwhere関数は条件合致した値を探すのにも使えますが、この関数の最も特徴的な部分は値に応じて条件分岐した処理を行うことができるということです。

本記事では

  • where関数の使い方
  • NumPyの関数を使った同様の処理の仕方

について解説します。

where関数

APIドキュメント

Pandasのwhere関数はSeriesとDataFrameのどちらにも実装されている関数ですが引数と使い方は全く一緒ですので、まとめてDataFrameのものを使って解説していきます。

以下のAPIドキュメントで使われているNDFrameというのはDataFrameの親クラスにあたるクラスです。多次元配列くらいの認識で問題ありません。

pandas.[DataFrame or Series].where(cond,other=nan,inplace=False,axis=None,level=None,errors=’raise’,try_cast=False,raise_on_error=None)

params:

パラメータ名 概要
cond bool値のNDFrame,配列
もしくは呼び出し可能なオブジェクト
Trueだと元のデータを保持し、Falseの場合、otherで指定された処理を実行するか値を代入します。
other スカラー,NDFrame
もしくは呼び出し可能なオブジェクト
(省略可能)初期値nan
condがFalseのときに実行する処理、もしくは代入する値を決めます。
inplace bool値 (省略可能)初期値False
出力された値を元のデータと入れ替えるかどうかを指定します。
axis 0または’index’
1または’columns’
(省略可能)初期値None
処理する方向を指定する必要がある時などに使います。
level 階層名,もしくは階層の段階 (省略可能)初期値None
どのIndexオブジェクトの階層を用いて値を処理するかを指定します。
errors 文字列,
‘raise’もしくは’ignore’
(省略可能)初期値’raise’
‘raise’のとき、例外が生じたときにエラーを発します。’ignore’のときはエラーを発しません。
try_cast bool値 (省略可能)初期値False
Trueにすると出力のデータ型を入力のデータ型に一致するように変換を試みます。
raise_on_error bool値 (省略可能)初期値True
(非推奨)無効な型に対してエラーを返すかどうか指定します。

returns:

条件分岐が適用されたDataFrame(もしくはSeries)が返されます。

condで指定された条件に合致している場合は特に何もせず、合致していない場合について特定の処理を行うというのがこの関数の基本的な使い方になります。

サンプルコード

では実際に使っていきます。

以下のデータを使って処理していきます。

In [1]: import pandas as pd

In [2]: import numpy as np # numpyもインポートしておく

In [3]: df = pd.DataFrame({
   ...:   'A': [1,2,3,-1,2,-2,5],
   ...:   'B': [3,3,6,-5,2,2,-1]
   ...: })

In [4]: df
Out[4]:
   A  B
0  1  3
1  2  3
2  3  6
3 -1 -5
4  2  2
5 -2  2
6  5 -1

otherを指定しない状態で条件だけを指定すると条件を満たすところは元のデータの値が、満たさないところは全てnanになります。

In [16]: df.where(df['A'] > 0, 0) # 特定の列の条件を使うことも可能
Out[16]:
   A  B
0  1  3
1  2  3
2  3  6
3  0  0
4  2  2
5  0  0
6  5 -1

In [17]: df.where(df>0, 0)  # 各々の要素について検討する
Out[17]:
   A  B
0  1  3
1  2  3
2  3  6
3  0  0
4  2  2
5  0  2
6  5  0

特定の列に対して処理を行うことも可能です。また、値の代入にSeriesやDataFrameを指定して値を指定することもできます。

In [19]: df['A'].where(df['A']>0, df['B']) # 他の列の値を代入
Out[19]:
0    1
1    2
2    3
3   -5
4    2
5    2
6    5
Name: A, dtype: int64


In [57]: df['B'].where(df['A']>0, df['B']*2) # 他の列データの条件を使うことも可能
Out[57]:
0     3
1     3
2     6
3   -10
4     2
5     4
6    -1
Name: B, dtype: int64

bool値のリストを渡しても同様のことができます。ブロードキャストは適用されないので同じ形状のものを用意する必要があります。

In [28]: mask = [True, True, True, False, False, False, True]

In [29]: df['A'].where(mask, 0)
Out[29]:
0    1
1    2
2    3
3    0
4    0
5    0
6    5
Name: A, dtype: int64

In [32]: masks = [[True, True],
    ...:          [False,True],
    ...:          [False,False],
    ...:          [True,True],
    ...:          [True,False],
    ...:          [True,False],
    ...:          [False,False]]
    ...:          

In [33]: df.where(masks,0)
Out[33]:
   A  B
0  1  3
1  0  3
2  0  0
3 -1 -5
4  2  0
5 -2  0
6  0  0

条件を満たさないときの処理は関数で指定することも可能。

In [35]: df.where(df>0,np.abs(df))
Out[35]:
   A  B
0  1  3
1  2  3
2  3  6
3  1  5
4  2  2
5  2  2
6  5  1

inplace=Trueにすると元のデータと置きかわります。

In [36]: df['C'] = df['A'].copy()

In [37]: df['C'].where(df['C'] <0, 0, inplace=True)

In [38]: df
Out[38]:
   A  B  C
0  1  3  0
1  2  3  0
2  3  6  0
3 -1 -5 -1
4  2  2  0
5 -2  2 -2
6  5 -1  0

文字列についても少し扱ってみます。

In [42]: df['D'] = ['abc','aaa','abb', 'acc', 'bcc','bbc','ccc']

In [43]: df
Out[43]:
   A  B  C    D
0  1  3  0  abc
1  2  3  0  aaa
2  3  6  0  abb
3 -1 -5 -1  acc
4  2  2  0  bcc
5 -2  2 -2  bbc
6  5 -1  0  ccc

‘a’を含まないものには"There is no a"という文字列と置き換えてみます。

In [53]: df['D'].where(df['D'].str.find('a')>-1, 'There is no a')
Out[53]:
0              abc
1              aaa
2              abb
3              acc
4    There is no a
5    There is no a
6    There is no a
Name: D, dtype: object

.strをつけるとPythonのstring型で使える関数を扱うことができます。これを使って’a’という文字列の検索を行いました。

他にも引数はあるのですが、ほとんど使われることがないため解説は割愛します。

numpyのwhere関数の適用

特に数値データで条件分岐をしたい場合、NumPyのwhere関数を使って処理を指定することも可能です。この場合便利なのはcond=Trueのときの値も変更できるというところにあります。

In [41]: np.where(df>0, 1, 0) # 0より大きいなら1,以下なら0
Out[41]:
array([[1, 1, 0],
       [1, 1, 0],
       [1, 1, 0],
       [0, 0, 0],
       [1, 1, 0],
       [0, 1, 0],
       [1, 0, 0]])

NumPyの関数numpy.whereの詳しい解説はこちら。

条件を満たす要素のインデックスを取得するNumPyのwhereの使い方 /features/numpy-where.html

まとめ

今回は条件を満たさない値の処理をするwhere関数の使い方について解説しました。使い勝手としてはNumPyのwhere関数の方がよく、数値データを扱うのが明確なときはこちらを使う方がやりやすいでしょう。

文字列の操作ではPandasの方が得意としているのでこちらを使ってデータ処理を行う方が便利です。

参考