人事評価データから昇進する人の背景を分析してみた


# はじめに
従業員の業績評価は、個々の成長はもとより、組織全体の進歩に寄与する要素です。適切な評価は、モチベーションの向上、キャリアパスの策定、そして人材の適正配置といった戦略的人事決定に不可欠です。今回のブログでは、プログラミング言語Pythonの力を借りて、これらの評価がどのように行われ、分析され、そして組織の決定に影響を与えるのかを探究します。

# 目的
この分析の目的は、人事評価データを通じて、昇進者の共通点や特徴を明らかにし、人事の意思決定プロセスにおける透明性と公平性を向上させるための洞察を得ることです。

# 実行環境
Python 3.7.12
kaggle notebook

# 実装したコード
```python
!pip install japanize-matplotlib
import japanize_matplotlib
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import plotly.express as px
from plotly.offline import init_notebook_mode
init_notebook_mode(connected=True)
```
```python
df=pd.read_csv("/kaggle/input/employees-evaluation-for-promotion/employee_promotion.csv")
```
### 読み込んだデータを表示
```python
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/7d57a312-d11b-e46d-fd01-e19794bca8fd.png)
### データに含まれる数値的特徴の統計情報
```python
df.describe()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/04c9c560-02f8-a9ac-fc26-f61941c92660.png)
### データフレームの構造を把握（欠損値を探しデータの補完）
```python
df.info()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/7155c97e-ac33-14f2-995f-8bfc712a626b.png)
### データフレーム内の各列の欠損値の個数を算出
```python
df.isnull().sum()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/6a8b55c3-e4dd-0b59-a00f-9bbac128e135.png)
### 欠損値を近くの値をもとに推測して補完しもう一度欠損値を算出
```python
df.interpolate(inplace=True)
df.isnull().sum()
```
### ここで補完できないデータが存在したので強制的に削除
```python
df.dropna(inplace=True)
df.isnull().sum()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/46d794d7-9c09-cfc8-9433-362ca81f46e7.png)
# ここから各カラムと昇進の関係性を可視化
### 従業員の学歴、受賞歴
```python
px.pie(df,values='awards_won',names='education',template='plotly_dark')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/ed302db3-b445-a056-905d-e443fa475c7c.png)
### 従業員の数と受賞歴
```python
plt.figure(figsize=(6,6))
sns.barplot(x='education',y='employee_id',hue='is_promoted',data=df)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/dc6da63b-66ff-80a4-e7e0-ee7bb73b421f.png)
### 従業員の男女比率
```python
sns.countplot(x='gender',data=df,palette='Greens_d')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/3cdeb79b-2bfa-4eb9-e635-b3b444a11d21.png)
### 男女別の年齢による昇進
```python
plt.figure(figsize=(17,6))
sns.violinplot(x='age',y='gender',hue='is_promoted',data=df)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/71524cde-d36b-7a04-fb0d-5ecb468a2d17.png)
##### *男性は30歳くらいが多く、女性は35歳くらいが多くなってます。なぜか年齢による違いがあるようです。
### 部門別に昇進した人
```python
px.pie(df,values='is_promoted',names='department',template = 'plotly_dark')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/55c89ab8-9768-77c6-61e8-3ac9b21c936b.png)
##### *部門別で人数の偏りがあるので割合にはかなりの誤差が見られます
### データの相関性
```python
df.corr()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/cf4afe4e-47db-8349-b201-b5697cc4bcb4.png)
### わかりやすくグラフ化
```python
plt.figure(figsize=(12,7))
sns.heatmap(df.corr(),annot=True,cmap='Blues')
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/480371c0-f113-5150-6a6d-6bc97bfe32df.png)
##### ＊色の濃い部分が関係性が強くなります。年齢（age）と勤続年（lenge_of_service）の数値が高くなってます。
### 予測
```python
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/a5de3703-d2b9-daf3-2e9d-244eb3d3edb3.png)
### 予測に必要のないと思われるカラムを削除します
```python
df.drop('employee_id',axis=1,inplace=True)
df.drop('region',axis=1,inplace=True)
df.drop('department',axis=1,inplace=True)
```
##### ＊社員id（employee_id）、各支店（region）、部署（department）
```python
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/4fbc5bdf-4a7f-89a9-4a64-98664b8403e0.png)
##### ＊カラムから削除したテーブルデータ
### 機械学習アルゴリズムで利用可能な形式(数値)に変換
```python
from sklearn.preprocessing import LabelEncoder
l=LabelEncoder()
for i in df.columns:
    if df[i].dtype == 'object':
        df[i]=l.fit_transform(df[i])
        
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/124bb6fb-f05d-3b33-d629-4893e69a8c84.png)
### カラム内を可視化
```python
import matplotlib.pyplot as plt

for i in range(len(df.columns)):
    print(df.columns[i])
    df[df.columns[i]].hist()
    plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/f35e6930-6c26-ce17-92d0-3fd999bb168f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/38bc2e7f-c193-f875-b0cd-b4f59190a46b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/031cd7d3-8059-4047-6b94-2fe21d303992.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/6c7b012c-6363-8004-b382-b0fbf0dea5bc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/cb8374f7-0994-ff6e-3f21-40bfbf7f89f5.png)
### データセットを特徴量（features）とターゲット変数（target variable）に分割
```python
x=df.drop('is_promoted',axis=1)
y=df['is_promoted']
```
＊
### 特徴量（x）とターゲット変数（y）のデータセットをトレーニングセットとテストセットに分割
```python
from sklearn.model_selection import train_test_split
xtrain,xtest,ytrain,ytest=train_test_split(x,y,test_size=0.30)
```
### 異なる特徴量が異なる範囲の値を共通のスケールに正規化する（各特徴量の最小値が0、最大値が1）
```python
from sklearn.preprocessing import MinMaxScaler
mms=MinMaxScaler(feature_range=(0,1))
xtrain=mms.fit_transform(xtrain)
xtest=mms.fit_transform(xtest)
xtrain=pd.DataFrame(xtrain)
xtest=pd.DataFrame(xtest)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/e379b7cc-6a13-ed57-4b2e-6f729bd2fd78.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/9b2760fb-7f58-a861-7554-70fdcc7e5f5f.png)
### 異なる機械学習モデルの評価指標を格納するための構造を定義
```python
R= {'Model':[],'Accuracy':[],'Recall':[],'Precision':[],'F1':[]}
```
### 機械学習モデルのパフォーマンスを比較するため視覚化するデータフレームを作成
```python
Results=pd.DataFrame(R)
Results.head()
```
### 機械学習のアルゴリズム（データから学習しタスクを実行するための予測モデルを構築）
```python
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier

lr=LogisticRegression()
dc=DecisionTreeClassifier()
rf=RandomForestClassifier()
kc= KNeighborsClassifier()

model=[lr,dc,rf,kc]

for models in model:
    models.fit(xtrain,ytrain)
    
    ypred=models.predict(xtest)
    
    
    print('Model :',models)
    print('-----------------------------------------------------------------------------------------------------------------------')
    from sklearn.metrics import confusion_matrix
    from sklearn.metrics import classification_report
    from sklearn.metrics import accuracy_score,recall_score,f1_score,precision_score
    
    print('confusion matrix :',confusion_matrix(ytest,ypred))
    print('classification report:',classification_report(ytest,ypred))
    print('accuracy :',round(accuracy_score(ytest,ypred),2))
    print('precision :',round(precision_score(ytest,ypred),2))
    print('recall :',round(recall_score(ytest,ypred),2))
    print('f1 :',round(f1_score(ytest,ypred),2))
    print()
    R={'Model':models,
             'Accuracy':round(accuracy_score(ytest,ypred),2),
             'Recall':round(recall_score(ytest,ypred),2),
             'Precision':round(precision_score(ytest,ypred),2),
             'F1':round(f1_score(ytest,ypred),2)
            }
    Results=Results.append(R,ignore_index=True)
```
#### LogisticRegression (ロジスティック回帰):

##### これは分類問題に使用される線形モデルで、特に二値分類問題に適しています。
##### 出力は0と1の間の確率として得られ、特定の閾値（通常は0.5）を超えると、対象がクラス1に属すると予測されます。
#### DecisionTreeClassifier (決定木分類器):

#### 決定木は、データを分類するために学習した一連の質問に基づいてモデルを構築します。
##### このモデルは、非線形関係にも適応でき、特徴量のスケーリングを必要としません。
#### RandomForestClassifier (ランダムフォレスト分類器):

##### ランダムフォレストは、多数の決定木を構築し、各木の予測の平均を取ることによって動作します（分類の場合は「多数決」方式）。
##### これにより、個々の決定木の過剰適合を防ぎ、より堅牢で精度の高いモデルが生成されます。
#### KNeighborsClassifier (k近傍分類器):

##### k近傍法は、与えられたデータポイントに最も近いk個のトレーニングサンプルを見て、それらの多数決に基づいてクラスを予測します。
##### この方法は非常に直感的であるが、大きなデータセットや高次元データセットでは計算コストが高くなる可能性があります。
### 分析結果の比較
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/ca96107a-621a-af2f-cc0d-f489ef5f98a0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/209659ca-dfb4-6ee6-85d5-7640f57c1e52.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/31570b21-7dd7-4862-a948-7070ec0d05cd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/07790bad-07d9-a5f4-8145-d27e7d8695ad.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/19ae315f-24c1-61c5-a5f5-97f7c61e355b.png)
##### Accuracy: モデルの正確さ（accuracy）を表す指標で、全予測のうち正しい予測の割合を示します。
##### Recall: 再現率（recall）または真陽性率（sensitivity）とも呼ばれ、実際の陽性サンプルのうち正しく陽性と予測されたサンプルの割合です。
##### Precision: 精度（precision）とは、陽性と予測されたサンプルのうち実際に陽性であるサンプルの割合です。
##### F1: F1スコアは、精度と再現率の調和平均を取ったもので、精度と再現率のバランスを示します。
# 勾配ブースティングマシン（Gradient Boosting Machines, GBM）
#### ＊上記のコードとは別により良い精度を求めて！　
##### 勾配ブースティングマシン（Gradient Boosting Machines, GBM）は、アンサンブル学習アルゴリズムの一種であり、特に教師あり学習の文脈で使用されます。アンサンブル学習は、複数の予測モデルを組み合わせて、単一のモデルよりも優れた予測を行う手法です。勾配ブースティングは、このアプローチの中でも特に強力な手法の一つとされています。

#### GBMは、弱い予測モデル（通常は決定木）の集合を段階的に構築します。各ステップで、現在のアンサンブルがデータに対してどのように間違った予測をしているか（すなわち、残差）に基づいて、新しいモデルが追加されます。この新しいモデルは、前のモデルの予測の誤差を最小化するように訓練されます。このプロセスは反復的に行われ、各反復で予測性能を少しずつ改善していきます。

#### 勾配ブースティングの「勾配」という用語は、各ステップで予測の残差に対して勾配降下法を用いることから来ています。勾配降下法は、予測誤差を減少させるためにモデルのパラメータを更新するための一般的な最適化手法です 
　
```python
#必要なモジュールのインストール
!pip install LightGBM
import numpy as np
import pandas as pd
import lightgbm as lgb
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score
import seaborn as sns


#XGBoostで学習するためのデータ形式に変換
dtrain = lgb.Dataset(xtrain, ytrain)
dvalid = lgb.Dataset(xtest, ytest)

#モデルパラメータの設定
params = {'objective':'multiclass','num_class':2,'metric' : {'multi_error'}}
model = lgb.train(params,dtrain)

#予測の実行と書き出し
pred_prob = model.predict(xtest)
pred = np.argmax(pred_prob,axis = 1)
print(pred)

#日本語対応
sns.set(font=['Meiryo','Yu Gothic'])



print('confusion matrix :',confusion_matrix(ytest,ypred))
print('classification report:',classification_report(ytest,ypred))
print('accuracy :',round(accuracy_score(ytest,ypred),2))
print('precision :',round(precision_score(ytest,ypred),2))
print('recall :',round(recall_score(ytest,ypred),2))
print('f1 :',round(f1_score(ytest,ypred),2))
print()


  
# 性能向上に寄与する度合いで重要度をプロット
lgb.plot_importance(model, height = 0.5, figsize = (8,16))
```
### GBMの主な特徴は以下のとおりです
##### 強力な予測能力:GBMは弱いモデルを多数組み合わせることで、非常に強力な予測モデルを構築できます。

##### 柔軟性:回帰、分類、ランキングなど、さまざまな種類の予測問題に対応できます。

##### 最適化:損失関数を最小化するように設計されており、カスタム損失関数を使用することもできます。

##### 過学習の抑制:学習率（shrinkage）やサブサンプリング（stochastic boosting）などのテクニックを使用することで、過学習を抑制することができます。
### 予測結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/d102465e-e926-bbdf-4513-e6d54f959f8a.png)
### 各カラムにおける重要度
```python
性能向上に寄与する度合いで重要度をプロット
lgb.plot_importance(model, height = 0.5, figsize = (8,16))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/bca07d0a-3928-7435-d5fe-450b4658b127.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/f795cdf8-c5f1-83e2-4aed-0a5161e42967.png)
![uploading...0]()
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616194/8a588982-bd9f-331f-85cf-0665b5d633e0.png)
![uploading...0]()
##### ＊このグラフからわかるようにデータフレームの８番目、６番目、４番目の順に重要視して目的変数を分析
# 考察
#### 分析の結果、平均研修スコア、年齢、一定期間以上の在籍は昇進の可能性を高めることが示唆されました。しかし、この分析では限定的なデータセットを使用しているため、さらに多角的なデータ収集と分析が必要であると考えられます。

#### また、平均研修スコアが高いことも昇進には重要であると考えられますが、この指標は主観的な評価に依存する可能性があります。従って、人事評価システムにおいて従って、人事評価システムにおいて、より客観的で透明な評価基準を設けることが重要であると考えられます。プロジェクトへの貢献度をより正確に測定するためには、複数の評価者による360度評価や、具体的な成果物に基づく評価など、様々なアプローチが考えられます。

#### さらに、在籍年数が長いと昇進の可能性が高まる傾向にあることから、組織に対する忠誠心や経験の蓄積が評価される文化があることが示唆されます。しかし、これが若手の才能が見過ごされる可能性を高めることも考慮する必要があります。

#### 最終的に、この分析は昇進に影響を与える可能性のある要因を浮き彫りにしましたが、これはあくまで一つの企業のデータセットに基づいた結果です。異なる業界や企業文化では、昇進の決定要因は異なる可能性があります。個々のスキルをどう評価に取り入れ更に評価基準を濃いものにしていく必要があるし適材適所で職務に従事できているかなど考慮は必要と感じます。そのため、一般化する前にはさらなる検証が必要です。

# 終わりに
#### この分析を通じて、人事評価データに潜むパターンを探ることができました。データ分析は人事戦略を形成する上で有力なツールですが、時に人材の離職につながることも懸念されます。データに基づく洞察を補完するためには、組織の文化や個々の従業員の独自性を理解することも同様に重要です。将来的には、データ駆動型のアプローチと従業員一人ひとりの個性を尊重する人事のバランスをとることが、企業にとって最適な人材育成と評価の方法となるでしょう。