Employee Attrition Prediction.
By: Rishma Mitra Dhar
Tags: Machine Learning, Data Visualization, Data Science, Data Analysis, Python

The data is for company X which is trying to control attrition. There are two sets of data: “Existing employees” and “Employees who have left”.

Following attributes are available for every employee :

Last evaluation

Number of projects.

Average monthly hours.

Time spent at the company.

Whether they have had a work accident.

Whether they have had a promotion in the last 5 years.

Departments (column sales).

Salary.

Whether the employee has left

Step 1 : We need to load our csv file. Link for the file :

Download Jupyter notebook using the command pip install jupyter (for Windows). And Let’s get started!

Importing all the necessary modules :

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import seaborn as sns

import warnings

warnings.filterwarnings('ignore')

Reading our file that is to be used :

excelfile=pd.ExcelFile("python.xlsx")

Emp_left=pd.read_excel(excelfile,'Employees who have left')

Emp_notleft=pd.read_excel(excelfile,'Existing employees')

Emp_left.tail()

Emp_notleft.head()

Emp_left.info() <class 'pandas.core.frame.DataFrame'>

RangeIndex: 3571 entries, 0 to 3570

Data columns (total 10 columns):

# Column Non-Null Count Dtype

--- ------ -------------- -----

0 Emp ID 3571 non-null int64

1 satisfaction_level 3571 non-null float64

2 last_evaluation 3571 non-null float64

3 number_project 3571 non-null int64

4 average_montly_hours 3571 non-null int64

5 time_spend_company 3571 non-null int64

6 Work_accident 3571 non-null int64

7 promotion_last_5years 3571 non-null int64

8 dept 3571 non-null object

9 salary 3571 non-null object

dtypes: float64(2), int64(6), object(2)

memory usage: 251.1+ KB

We see how many employees are there in each department :

Emp_left.dept.value_counts() sales 1014

technical 697

support 555

IT 273

hr 215

accounting 204

marketing 203

product_mng 198

RandD 121

management 91

Name: dept, dtype: int64

Now we combine the IT , Support and Technical in one value as Technical.

Emp_left[‘dept’]=np.where(Emp_left[‘dept’]==’support’,’technical’,Emp_left[‘dept’]).astype(‘str’)

Emp_left[‘dept’]=np.where(Emp_left[‘dept’]==’IT’,’technical’,Emp_left[‘dept’]).astype(‘str’)

Emp_notleft[‘dept’]=np.where(Emp_notleft[‘dept’]==’support’,’technical’,Emp_notleft[‘dept’]).astype(‘str’)

Emp_notleft[‘dept’]=np.where(Emp_notleft[‘dept’]==’IT’,’technical’,Emp_notleft[‘dept’]).astype(‘str’)

Step 2 : We start to compare values of the employees based on each factor and the reason why they are leaving.

plt.figure(figsize=(20,12))

plt.title("Last evaluation vs Satisfication level")

sns.scatterplot(x=Emp_left['satisfaction_level'],y=Emp_left['last_evaluation'],hue='number_project',data=Emp_left, palette='bright')

plt.show()

Point drawn from above plot:

Satisfaction level is very low for employees who has number of projects more than 4

Last evaluation for employees having number of projects equal to 2 is low, also they have low satisfaction level.

Step 3 : We now compare the Salary vs Satisfaction level based on the time spent in the company:

plt.figure(figsize=(20,10))

plt.title(‘Salary vs Satisfaction level’)

sns.boxplot(x=Emp_left[‘salary’],y=Emp_left[‘satisfaction_level’],hue=’time_spend_company’,data=Emp_left)

plt.show()

Step 4 : Just to analyze the perfect reason we draw a boxplot for the Salary vs the Monthly hours spent based upon the number of projects that they have done.

plt.figure(figsize=(20,10))

plt.title(“Salary vs Monthly hours spent”)

sns.boxplot(x=Emp_left[‘salary’],y=Emp_left[‘average_montly_hours’],hue=’number_project’,data=Emp_left)

plt.show()

Step 5 : Some more boxplots to know more reasons for why the employees left:

plt.figure(figsize=(20,10))

plt.title(“Average monthly hours vs Promotion in last 5 years”)

sns.boxplot(x=Emp_left[‘promotion_last_5years’],y=Emp_left[‘average_montly_hours’],hue=’time_spend_company’,data=Emp_left)

plt.show()

plt.figure(figsize=(20,10))

plt.title(‘Average monthly hours vs Number of projects’)

sns.boxplot(x=Emp_left[‘number_project’],y=Emp_left[‘average_montly_hours’],data=Emp_left)

plt.show()

We now see which department has the most number of employees leaving :

Points to ponder over —

Sales and Technical employees are the maximum number who are leaving.

Step 6 : As we have seen that technical employees are the most number of people leaving the company. We now see the department vs satisfaction level of the employees based upon the time spend in the company.

plt.figure(figsize=(18,10))

plt.title(“Department vs Satisfcation level”)

sns.boxplot(x=Emp_left[‘dept’],y=Emp_left[‘satisfaction_level’],hue=’time_spend_company’,data=Emp_left)

plt.show()

Step 7 : Finding the proportion of employees leaving from the company :

# Adding both dataset from employees who left with the existing employees Emp_left[‘Left’]=1

Emp_notleft[‘Left’]=0

final_Emp=pd.concat([Emp_left,Emp_notleft],axis=0)

final_Emp.info() # Creating dummies

columns=[‘dept’,’salary’]

dummies=pd.get_dummies(final_Emp[columns],drop_first=True)

final_Emp=pd.concat([final_Emp,dummies],axis=1)

final_Emp.head() # Dropping uncessary columns

final_Emp=final_Emp.drop(columns,axis=1)

final_Emp.info() # Dividing the dataset into X and Y

X=final_Emp.drop([‘Emp ID’,’Left’],axis=1)

y=final_Emp[‘Left’]

print(“The proportion of employees left is {}% from total dataset”.format(round(final_Emp.Left.value_counts()[1]/len(final_Emp)*100,2)))

The proportion of employees left is 23.81% from total dataset.

We use the following techniques for the approach of finding out about the employees prone to leave by measuring the accuracy of each technique.

The techniques are:

Logistic regression.

Random forest classifier.

Support vector classifier.

Oversampling.

From the above observations, we found the “Random Forest Classifier” had the highest accuracy. Therefore we build a model based on that.

# Random Forest from sklearn.model_selection import GridSearchCV

from sklearn.model_selection import KFold rfc=RandomForestClassifier(random_state=50) n_folds=KFold(n_splits=5,shuffle=True, random_state=50) parameters={'criterion':['gini','entropy'],'max_depth': range(5,30,5),'max_features': range(10,18,2),

'min_samples_split': range(2,10,2)} model_cv = GridSearchCV(estimator=rfc,param_grid=parameters,cv=n_folds,verbose=1,

return_train_score=True,scoring='recall')

final_rfc=RandomForestClassifier(criterion='entropy',max_depth=20,max_features=14,min_samples_split=2,random_state=50)

final_rfc.fit(X_train.drop('Emp ID',axis=1),y_train)

y_pred=final_rfc.predict(X_test.drop('Emp ID',axis=1)) from sklearn.metrics import classification_report

print(classification_report(y_test,y_pred))

final_rfc.feature_importances_

X_train.columns

features=np.array(X_train.drop('Emp ID',axis=1).columns)

important=final_rfc.feature_importances_

indexes_features=important.argsort()

for i in indexes_features:

print("{} : {:.2f}%".format(features[i],important[i]*100)) # Finding employees who are prone to leave : y_test1=pd.concat([y_test,X_test[‘Emp ID’]],axis=1)

y_test3=pd.DataFrame(y_pred) y_test3.reset_index(inplace=True, drop=True) gf=pd.concat([y_test1.reset_index(),y_test3],1) new_df=gf[gf.Left==0] new_df=new_df.drop(‘index’,axis=1) new_df.columns=[‘Left’,’Emp ID’,’Predicted_left’] Employees_prone_to_leave=new_df[new_df[‘Predicted_left’]==1]

Employees_prone_to_leave=Employees_prone_to_leave.reset_index()

Employees_prone_to_leave=Employees_prone_to_leave.drop([‘Left’,’Predicted_left’,’index’],axis=1)

FINAL OUTPUT : (EMPLOYEES PRONE TO LEAVE)

Emp ID

0 6467

1 2416

2 9176

3 9241

4 5200

5 9057

6 2802

7 3862

8 4770

Factors driving employees to leave :

Below are some important features with % contribution towards attrition.

Satisfaction level : 34.63%

Time spend in the company : 27.47%

Average monthly hours : 10.84%

Last Evaluation : 12.14%

Number of projects : 9.25%

These are the driving factors which leads an employee to leave the company.

The accuracy of this model is 93.33 percent which is pretty good ! Thank you for reading this article till the end.