データの前処理でpandasのデータフレームで特定の列に対して、その数値を2倍にするなど同じような処理を実施したい、特定条件で1、0に置換してフラグにしたい・・・なんて時があります。データフレームの列に対してfor文を回すことでも実装可能ですが、データフレームに対してfor文を使うと処理がとても遅くなるのでナンセンスです。
無名関数(lambda)を使う
こういった場合基本的に無名関数(lamda)を使用するのが一般的です。
例えば以下のようなデータがあったとします。
data = [ [1, 2, 3], [2, 4, 6], [3, 6, 9], [4, 8, 12] ] data = pd.DataFrame(data) data.columns = ['a', 'b', 'c'] data
<実行結果>
このデータフレームのaの列の数値を2倍にしたいときは以下のように記述します。
#列aの要素を2倍にする data['a'].apply(lambda x : x * 2)
<結果>
0 2 1 4 2 6 3 8 Name: a, dtype: int64
applyとlambdaとif文で条件分岐して一括変換
またapplyとlambdaにif文を組み合わせて条件分岐して置換することも可能です。データ分析の前処理とかだと文字列や数値を特定の条件で1か0のフラグに変換する処理はデータの前処理でよくやるので是非使いこなせるようになっておきたいところです。
# 列aの要素が3より大きい場合は1に置換、それ以外の場合は0に置換 data['a'].apply(lambda x : 1 if x > 3 else 0)
<結果>
0 0 1 0 2 0 3 1 Name: a, dtype: int64
elifが絡んでくる条件分岐も以下のように記述できます。まあここまで条件が多くなると普通に関数を定義しておいたほうがいいかもですね。
# elifが絡んだ条件分岐 data['a'].apply(lambda x : 'xは1未満です' if x < 1 else ('xは1以上2未満です' if x >= 1 and x < 2 else('xは2以上3未満です' if x >= 2 and x < 3 else 'xは3以上です')))
<結果>
0 xは1以上2未満です 1 xは2以上3未満です 2 xは3以上です 3 xは3以上です Name: a, dtype: object
列に対して関数処理を実行する
また条件分岐などが多く関数が1行で記述するのが難しいくらい冗長になる場合は関数をあらかじめ定義しておいてそれをapplyを用いて列に対して実行することも可能です。
この際戻り値(return x の部分)を設定しないと全部Noneになるので注意してください
<例>
# 偶数なら1を加算する関数 def replace(x): if x % 2 == 0: x = x+1 else: pass return x # replace()をdataのa列に適用する data['a'].apply(lambda x : replace(x))
<実行結果>
astype系のメソッドだと欠損値が出た場合にエラーになりますが
この要領でtry exceptの例外処理を組み込むことでエラーを無視したデータ型の変換も可能です
備考
型変換を行いたい場合は、日付型であれば列に対してto_datetime()などで一括変換が可能です。またapplyは欠損値やNONEがあるとエラーになることがあるので、欠損値処理などを事前にしておくとスムーズに処理が捗ります
また置換した結果で新しい列を作りたい場合は以下のようにします。
# 列aの要素を2倍にした新しい列(new_column)を作る data['new_column'] = data['a'].apply(lambda x : x * 2)
コメント
[…] 参照:【Python】データフレームの列データをapply関数+lambdaで条件分岐してまとめて置換する […]
[…] 関連記事:pandasの列データをapplyとlambdaで条件分岐して置換する […]