日々学び、感謝し、成長する

データとハートを活かす人事を目指した成長奮闘記(?)です

Pythonでデータ分析に必要な前処理:数値化

f:id:millebon:20210723192632p:plain

 

統計分析で一番時間がかかるのが前処理。。

Pythonでデータ分析を行うときに一番時間がかかるのが前処理です。

 

多くの分析の下となるデータはデータ分析がしやすいように集められていないことが普通です。

 

まず、データ分析でとりわけ回帰分析を行うにおいて必要なのがデータを数値化や数値の重みを統一化すること。でも人事関連のデータには数値でないものがたくさん含まれていますし、数値の値もバラバラだったりします。

 

それをどう数値化するか?今受講中の講座でいただいたヒントを基にPythonでの数値化の方法と正規化について自分も備忘録もかねてまとめたいと思います。

 

カテゴリー変数を0か1かに変換(map変数を活用)

Pythonにはpandasにダミー変数化できる関数(get_dummies)があり、こちらを使うことが多いかもしれませんが、この関数を使うと1)変数が増える、2)また2択といった相関性が明らかなものの場合回帰分析には使えなくなります。

 

まあ、後で削除すればいいだけといえばそうなのですが、別のやり方としてはmap関数を用いて、同じ列である場合は0、別の場合は1という風に0か1に変換します。

 

例えば採用区分に以下のようなデータが入っていた場合、新卒を0、中途を1に変換するということですね。

f:id:millebon:20210723194938p:plain

 

こちらはmap関数を使えば2行で簡単にできます。

hiring_map={"新卒": 0, "中途": 1}

df["採用区分"] = df["採用区分"].map(hiring_map)

 

注意:dfはデータが入っているDataFrameの変数名です。以下同様

 

 

私は列数を増やしたくなかったので、採用区分の列を上書きして0、1に変換しました。違う列にしたい場合は列名を変更してくださいね。

 

この方法ですが、もとのデータが3つ以上の分類のものを0、1の2つの分類に変えたいときにも使えます。

例えば、役職名データを管理職(課長クラス、次長クラス)であれば1、非管理職であれば0というような場合ですね。

f:id:millebon:20210723195904p:plain

その場合は以下のように辞書の定義(以下の場合ですと、mgr_mapという変数に入っている辞書です)をそのように設定すればいいだけです。

mgr_map={"主担当": 0,"副担当": 0, "課長クラス": 1,"次長クラス": 1,"部長クラス": 1}

df["タイトル(管理職有無)"] = df["タイトル"].map(mgr_map)

 

条件式を使って0か1に変換

0か1の変更は条件式を使って行いたい場合もあるかと思います。

 

例えば、転職回数が3回以上の人には1というフラグを、それ以下の人には0というフラグを立てる。

 

f:id:millebon:20210723200925p:plain

その場合はapply関数とlambdaを利用して以下のように書きます。

change=lambda x:1 if x>=3 else 0

df["転職回数3回以上"] = df["転職回数"].apply(change)

 

さすがに内容が異なるので違う列名で作成しました!

 

これを応用して2つの列の比較から新たな0、1のフラグを立てる列を作るということもできます。

 

以下のように前年と直近の評価を比べて、直近の評価が前年評価より低い場合(直近評価-前年評価が0より小さい場合)は1、そうでない場合は0というような感じです。

f:id:millebon:20210723201254p:plain

これは以下のように書けますね。

df["前年からの評価低下_P"]=df["直近評価"]-df["前年評価"]

p_change=lambda x:1 if x<0 else 0

df["前年からの評価低下"] = df["前年からの評価低下_P"].apply(p_change)

 

(最小最大)正規化で連続数値の重みを統一化

(最小最大)正規化というのは、数値データからなる項目を最小値が0、最大値が1となるように特徴量を正規化する処理です。

 一般的には単に正規化といわれているのですが、私がよく参照させてもらっている”Pythonによるデータ分析の教科書"では、分散正規化(平均を0、標準偏差が1となるように変換する処理。一般的に標準化といわれています)と区別してそのように書いていたのでカッコ書きで使うことにしました(自分も標準化とよく間違うので😋)

 

数式で書くと以下のような式になります。

  X’=(X-Xmin)/ X max -Xmin

 

が、実際の例で見てもらった方がよくわかると思います。

 

人事関係のデータではこのようにアンケートであったり在籍年数、時間外、有給取得など、例えば退職者のプロフィールの予測の回帰分析を作ったりするのに幅の異なる連続数値を使うことがあります。

 

そういう時に便利な方法ですね。

f:id:millebon:20210724141831p:plain



PythonではScikit-Learnでpreprocessingモジュールというのを使って行います。

データフレームの一部の列を変更したい場合はminmax_scaleが便利ですね。ただし、数値は浮動小数点でなければならないので、整数の場合浮動小数点に変更する処理が必要となります。

 

from sklearn import preprocessing

a=df['在籍年数'].astype(float)

df['在籍年数']=preprocessing.minmax_scale(a)

 

ただし、このminmax_scaleを使う方法はその後データの精度を検証するために学習データとテストデータに分類する前に行うのには向かないそうです。。(私にはまったく理由がわからなかったのですが、Scikit-Learnの説明をご覧ください)

 

MinMaxScaler()を使いつつ一番めんどくさくない方法は。。ということでいろいろググると以下のような形だと比較的楽かなと思いました。

from sklearn.preprocessing import MinMaxScaler

mmsc= MinMaxScaler()

df['在籍年数']=mmsc.fit_transform(df['在籍年数'].values.reshape(-1,1))

 

for文とかを使えば複数の列も同じようにできるのかもしれませんが、相変わらず苦手で😥..次回の課題にしたいと思います。