1.需求描述
本文分析利用DC员工数据进行分析。在对离职率的影响因素进行观察的基础至上,建立模型并预测哪些员工更易离职。
2.数据集描述
DC员工数据集共有31个变量,1100个观测量。部分重点关注变量描述如下:
重点字段描述
员工特征可以分为以下几类
- 基本的身份信息变量:性别、年龄、学历、婚姻状况、教育程度、就读专业;
- 员工公司身份变量:工龄、司龄(在公司工作的时间)、职位、职级、任职过的企业数量、所在部门、商务差旅情况、和目前管理者共事年数
- 薪酬与福利变量:月薪、工作投入、是否加班、绩效评分、认购优先股的级别、涨薪比列、上年度培训次数、距离上次升职的时间间隔
- 生活质量相关变量:工作环境满意度、工作满意度、关系满意度、工作与生活平衡情况、上班距离
3.特征分析
3.1 统计分析
基础信息描述
-
员工基础信息描述
- 员工员工平均年龄约37岁,最大的60岁,最小的18岁;
- 全部1100名员工中,离职178人,离职率16.2%;
- 员工平均收入6483.6,中位收入4857.0,最小1009,最大19999;
- 员工中男性为653人、女性为447人;男性离职率为61.2%、女性离职率为38.8%
3.2 分布分析
通过对部分变量观察分析,发现以下问题:
-
18岁-23岁员工离职率超过40%,符合当前市场对95后司龄的判断,25岁以后员工稳定性趋于稳定,维持在20%-40%之间
-
研发部门离职人数最多,这主要是因为该公司研发部门人数最多的原因,虽然人数多,但是研发部门离职率最低,离职率最高的部门是HR,该部门也是公司人数最少的部门(基数比较小)
-员工离职率和薪资涨幅比呈现负相关,当涨幅比最大时员工离职率超过40%,有点奇怪,如果分析没有错误那就说明该部分员工薪资基数较小故而导致离职率很高
PercentSalaryHike&MonthlyIncome.png -
工作投入度等级为1的员工离职率有近40%,达到了38%!!!一分耕耘一份收获,若未付出何谈喜欢?
JobInvolvement.png -
员工加班的离职率是不加班离职率的3倍!!!弹性工作和不加班为什么会成为一种福利待遇
员工在公司供职时间越长稳定性越好,员工司龄在0年-2年内离职率最高为35.8%,20年-25年会有小幅增长(有可能会创业或者升职无望),31年-32年离职率会上升达到33%根据一般就职年限计算员工在未被企业返聘的情况下应该已退休
-
工作环境和工作满意度体现:工作满意度比较低、环境满意度低都会导致员工流失率增加
4.特征选择
4.1数据预处理
-
对特征类别进行分类:数值类和非数值类
def obtain_x(train_df,xtype): dtype_df = train_df.dtypes.reset_index() dtype_df.columns = ['col','type'] return dtype_df[dtype_df.type != xtype].col.values float64_col = obtain_x(train_local,'object') #float64
-
加载数据进行归一化处理
min_max_scaler = preprocessing.MinMaxScaler() X = min_max_scaler.fit_transform(X)
-
加载数据对类别数据进行编码处理
le = preprocessing.LabelEncoder() ohe = preprocessing.OneHotEncoder() train = pd.DataFrame() local_all = pd.concat([train_local,test_local],axis=0) for col in object_col: le.fit(local_all[col]) local_all[col] = le.transform(local_all[col]) ohe.fit(local_all[col].reshape(-1, 1)) ohecol = ohe.transform(local_all[col].reshape(-1, 1)).toarray() ohecol = pd.DataFrame(ohecol[:,1:],index=None)#columns=col+le.classes_ ohecol.columns = ohecol.columns.map(lambda x:str(x)+col) train = pd.concat([train2, ohecol],axis=1, ignore_index=False)
4.2 计算相关系数
-
计算各变量对离职率的影响程度
print(train.corr()['Attrition']) x = train.corr()['Attrition'].index y = train.corr()['Attrition'].values plt.figure(figsize=(12,5)) plt.plot(x,y, 'b.-',label="皮尔逊相关系数") plt.legend() plt.ylabel("皮尔逊相关系数") plt.xlabel("变量名称") plt.xticks(rotation=45) plt.grid() for i,j in zip(x,y): plt.text(i,j+0.005,'%.2f' %(j),ha='center',va='bottom') ` ``
4.3 利用特征的统计信息进行特征选择
-
移除低方差特征
from sklearn.feature_selection import VarianceThreshold sel = VarianceThreshold() train_all_sel = sel.fit_transform(train_all) train_local4 = train_all.iloc[0:len(train_local)] test_local4 = train_all.iloc[len(train_local):] # 定义特征统计函数 def col_Sta(train_df): col_sta = pd.DataFrame(columns = ['_columns','_min','_max','_median','_mean','_ptp','_std','_var']) for col in train_df.columns: col_sta = col_sta.append({'_columns':col,'_min':np.min(train_df[col]),'_max':np.max(train_df[col]),\ '_median':np.median(train_df[col]),'_mean':np.mean(train_df[col]),\ '_ptp':np.ptp(train_df[col]),'_std':np.std(train_df[col]),'_var':np.var(train_df[col])},ignore_index=True) return col_sta train_col_sta = col_Sta(train_local4) test_col_sta = col_Sta(test_local4) train_col_sta
-
计算卡方信息量
from sklearn.feature_selection import chi2#调用卡方信息量 chi2_col,pval_col = chi2(train_local4[feature_end].values,train_y)
-
计算F信息量
from sklearn.feature_selection import f_classif#调用f信息量 f_col,pval_col = f_classif(train_local4[feature_end].values,train_y)
-
计算互信息量
from sklearn.feature_selection import mutual_info_classif#调用互信息 mic_col = mutual_info_classif(train_local4[feature_end].values,train_y)
5 建模
5.1 逻辑回归预测
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
train_x_0 = train_local[['EnvironmentSatisfaction','JobInvolvement','JobSatisfaction','YearsSinceLastPromotion']]#RelationshipSatisfaction
train_y_0 = train_local[y_col]
clf = LogisticRegression(C=10)
clf.fit(train_x_0, train_y_0)
scores = cross_val_score(clf, train_x_0, train_y_0)
print(scores.mean()) #0.8370006974003799
x_col = [x for x in float64_col if x not in ['Attrition']]
len(x_col)
y_col = 'Attrition'
train_x = train_local[x_col]
train_y = train_local[y_col]
clf = LogisticRegression(C=10)
clf.fit(train_x, train_y)
scores = cross_val_score(clf, train_x, train_y)
print(scores.mean()) #0.8469807373205397
5.2 随机森林预测
from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(n_estimators=100, max_depth=5,min_samples_split=2, random_state=0)
clf = clf.fit(train_local4[feature_end], train_y)
scores = cross_val_score(clf, train_local4[feature_end], train_y)
print(scores.mean()) # 0.8470288338984681
5.3 组合筛选创建模型
feature_a = feature_sel[(feature_sel['importance']>=0.005)].feature.values
clf = LogisticRegression(C=10)
clf.fit(train_x3[feature_a], train_y)
scores = cross_val_score(clf, train_x3[feature_a], train_y)
print(scores.mean()) #0.8729528894019191
5.4混淆矩阵评估模型
TP(真实为1): 7
FP(真实为0): 3
TN(真实为0): 83
FN(真实为1): 7
P: 0.7
R: 0.5
ACC: 0.9
发现准确率和召回率都是很很满意,模型预测准确度也很不错