京公网安备 11010802034615号
经营许可证编号:京B2-20210330
CDA数据分析师 出品
作者:真达、Mika
数据:真达
后期:泽龙
【导读】
今天教大家如何用Python写一个员工流失预测模型。Show me data,用数据说话。我们聊一聊员工离职,说到离职的原因,可谓多种多样。人们归总了两点:
1. 钱没给到位
2. 心受委屈了
有人离职是因为“世界那么大,我想去看看”,也有人觉得“怀有绝技在身,不怕天下无路”。
另一方面,员工离职对于企业而言有什么影响呢?
要知道,企业培养人才需要大量的成本,为了防止人才再次流失,员工流失分析就显得十分重要了。这不仅仅是公司评估员工流动率的过程,通过找到导致员工流失的主要因素,预测未来的员工离职状况,从而进一步减少员工流失。
那么,哪些因素最容易导致员工离职呢?
这次我们用数据说话,
教你如何用Python写一个员工流失预测模型。
01、数据理解
我们分析了kaggle平台分享的员工离职相关的数据集,共有10个字段14999条记录。数据主要包括影响员工离职的各种因素(员工满意度、绩效考核、参与项目数、平均每月工作时长、工作年限、是否发生过工作差错、5年内是否升职、部门、薪资)以及员工是否已经离职的对应记录。字段说明如下:
02、读入数据
# 读入数据 df = pd.read_csv('HR_comma_sep.csv')
df.head()
# 读入数据 df = pd.read_csv('HR_comma_sep.csv')
df.head()
# 读入数据 df = pd.read_csv('HR_comma_sep.csv')
df.head()
# 查看缺失值 print(df.isnull().any().sum())
# 查看缺失值 print(df.isnull().any().sum())
# 查看缺失值 print(df.isnull().any().sum())
可以发现,数据质量良好,没有缺失数据。
03、探索性分析
描述性统计
df.describe().T
从上述描述性分析结果可以看出:
离职人数占比
整理数据后发现,总共有14999人,其中红色部分代表离职人群,用数字1表示,蓝色为未离职人群,用数字0表示。离职人数为3571,占总人数的23.8%。
员工满意度
从直方图可以看出,离职员工的满意度评分明显偏低,平均值为0.44。满意度低于0.126分的离职率为97.2%。可见提升员工满意度可以有效防止人员流失。
df.groupby('left')['satisfaction_level'].describe()
def draw_numeric_graph(x_series, y_series, title): # 产生数据 sat_cut = pd.cut(x_series, bins=25)
cross_table = round(pd.crosstab(sat_cut, y_series, normalize='index'),4)*100 x_data = cross_table.index.astype('str').tolist()
y_data1 = cross_table[cross_table.columns[1]].values.tolist()
y_data2 = cross_table[cross_table.columns[0]].values.tolist()
# 条形图 bar = Bar(init_opts=opts.InitOpts(width='1350px', height='750px'))
bar.add_xaxis(x_data)
bar.add_yaxis(str(cross_table.columns[1]), y_data1, stack='stack1', category_gap='0%')
bar.add_yaxis(str(cross_table.columns[0]), y_data2, stack='stack1', category_gap='0%')
bar.set_global_opts(title_opts=opts.TitleOpts(title),
xaxis_opts=opts.AxisOpts(name=x_series.name, name_location='middle', name_gap=30),
yaxis_opts=opts.AxisOpts(name='百分比', name_location='middle', name_gap=30, min_=0, max_=100),
legend_opts=opts.LegendOpts(orient='vertical', pos_top='15%', pos_right='2%'))
bar.set_series_opts(label_opts=opts.LabelOpts(is_show=False),
itemstyle_opts=opts.ItemStyleOpts(border_color='black', border_width=0.3))
bar.set_colors(['#BF4C51', '#8CB9D0'])
return bar
bar1 = draw_numeric_graph(df['satisfaction_level'], df['left'], title='满意度评分与是否离职')
bar1.render()
绩效考核
平均来看,绩效考核成绩在离职/未离职员工之间差异不大。在离职员工中,绩效考核低、能力不够和绩效考核较高但工作压力大、满意度低、对薪资不满意可能成为离职的原因。
平均每月工作时长
从直方图可以看出,月工作时长正常的员工离职率最低。而工时过低、过高的员工离职人数最多。证明恰当的工作任务分配是非常重要的。
参加项目数
从图中可以看出:除项目数为2以外,随着项目数的增多,离职率在增大,且项目数是7的时候,离职率达到了100%以上。综上两点,项目数2的离职率高,可能是这部分人工作能力不被认可。项目数6、7的总体少,离职率高,体现了他们的工作能力强,但同时工作压力太大导致他们离职。
员工工龄
可以看到7年及以上工龄的员工基本没有离职,只有工龄为5年的员工离职人数超过在职人数。可见工龄长于6年的员工,由于种种原因,其“忠诚度”较高。
而员工进入公司工作的第5年是一个较为“危险”的年份,也许是该企业的“5年之痒”,应当重点关注该阶段的员工满意度、职业晋升等情况,以顺利过渡。
工作事故
从图中可看出,是否发生工作事故对员工离职的影响较小,可推测该企业处理工作事故的方式有可取之处。
职位晋升
从条形图可以看出,在过去5年内获得未晋升的员工离职率为24.2%,比获得晋升的员工高4倍。设定良好的晋升通道可以很好的防止员工流失。
薪资水平
可明显看出,薪资越高离职人数越少。证明为了减少离职率,提升员工福利待遇是一个可行的手段。
不同部门
可见各部门离职率如上图,离职率由高到低,前三位分别是:人力部、财务部、科技部。之后依次是:支持部、销售部、市场部、IT部门、产品部、研发部、管理部。对于离职率过高的部门,应进一步分析关键原因。
04、数据预处理
由于sklearn在建模时不接受类别型变量,我们主要对数据做以下处理,以方便后续建模分析:
# 数据转换 df['salary'] = df['salary'].map({"low": 0, "medium": 1, "high": 2}) # 哑变量 df_dummies = pd.get_dummies(df,prefix='sales')
df_dummies.head()
05、建模分析
from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, f1_score, roc_curve, plot_roc_curve
然后划分训练集和测试集,采用分层抽样方法划分80%数据为训练集,20%数据为测试集。
train_pred = GS.best_estimator_.predict(X_train)
test_pred = GS.best_estimator_.predict(X_test) print('训练集:', classification_report(y_train, train_pred)) print('-' * 60) print('测试集:', classification_report(y_test, test_pred))
我们使用决策树进行建模,设置特征选择标准为gini,树的深度为5。输出分类的评估报告:
# 训练模型 clf = DecisionTreeClassifier(criterion='gini', max_depth=5, random_state=25)
clf.fit(X_train, y_train)
train_pred = clf.predict(X_train)
test_pred = clf.predict(X_test) print('训练集:', classification_report(y_train, train_pred)) print('-' * 60) print('测试集:', classification_report(y_test, test_pred))
训练集: precision recall f1-score support 0 0.98 0.99 0.98 9142 1 0.97 0.93 0.95 2857 accuracy 0.98 11999 macro avg 0.97 0.96 0.97 11999 weighted avg 0.98 0.98 0.97 11999 ------------------------------------------------------------ 测试集: precision recall f1-score support 0 0.98 0.99 0.98 2286 1 0.97 0.93 0.95 714 accuracy 0.98 3000 macro avg 0.97 0.96 0.97 3000 weighted avg 0.98 0.98 0.98 3000
假设我们关注的是1类(即离职类)的F1-score,可以看到训练集的分数为0.95,测试集分数为0.95。
# 重要性 imp = pd.DataFrame([*zip(X_train.columns,clf.feature_importances_)], columns=['vars', 'importance'])
imp.sort_values('importance', ascending=False)
imp = imp[imp.importance!=0]
imp
在属性的重要性排序中,员工满意度最高,其次是最新的绩效考核、参与项目数、每月工作时长。
然后使用网格搜索进行参数调优。
parameters = {'splitter':('best','random'),
'criterion':("gini","entropy"),
"max_depth":[*range(1, 20)],
}
clf = DecisionTreeClassifier(random_state=25)
GS = GridSearchCV(clf, parameters, cv=10)
GS.fit(X_train, y_train) print(GS.best_params_) print(GS.best_score_)
{'criterion': 'gini', 'max_depth': 15, 'splitter': 'best'}
0.9800813177648042
使用最优的模型重新评估训练集和测试集效果:
train_pred = GS.best_estimator_.predict(X_train)
test_pred = GS.best_estimator_.predict(X_test) print('训练集:', classification_report(y_train, train_pred)) print('-' * 60) print('测试集:', classification_report(y_test, test_pred))
训练集: precision recall f1-score support 0 1.00 1.00 1.00 9142 1 1.00 0.99 0.99 2857 accuracy 1.00 11999 macro avg 1.00 0.99 1.00 11999 weighted avg 1.00 1.00 1.00 11999 ------------------------------------------------------------ 测试集: precision recall f1-score support 0 0.99 0.98 0.99 2286 1 0.95 0.97 0.96 714 accuracy 0.98 3000 macro avg 0.97 0.98 0.97 3000 weighted avg 0.98 0.98 0.98 3000
可见在最优模型下模型效果有较大提升,1类的F1-score训练集的分数为0.99,测试集分数为0.96。
下面使用集成算法随机森林进行模型建置,并调整max_depth参数。
rf_model = RandomForestClassifier(n_estimators=1000, oob_score=True, n_jobs=-1,
random_state=0)
parameters = {'max_depth': np.arange(3, 17, 1) }
GS = GridSearchCV(rf_model, param_grid=parameters, cv=10)
GS.fit(X_train, y_train) print(GS.best_params_) print(GS.best_score_)
{'max_depth': 16} 0.988582151793161
train_pred = GS.best_estimator_.predict(X_train)
test_pred = GS.best_estimator_.predict(X_test) print('训练集:', classification_report(y_train, train_pred)) print('-' * 60) print('测试集:', classification_report(y_test, test_pred))
训练集: precision recall f1-score support 0 1.00 1.00 1.00 9142 1 1.00 0.99 0.99 2857 accuracy 1.00 11999 macro avg 1.00 1.00 1.00 11999 weighted avg 1.00 1.00 1.00 11999 ------------------------------------------------------------ 测试集: precision recall f1-score support 0 0.99 1.00 0.99 2286 1 0.99 0.97 0.98 714 accuracy 0.99 3000 macro avg 0.99 0.99 0.99 3000 weighted avg 0.99 0.99 0.99 3000
可以看到在调优之后的随机森林模型中,1类的F1-score训练集的分数为0.99,测试集分数为0.98。
模型后续可优化方向:
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
在数据分析中,“正态分布” 是许多统计方法(如 t 检验、方差分析、线性回归)的核心假设 —— 数据符合正态分布时,统计检验的 ...
2025-10-28箱线图(Box Plot)作为展示数据分布的核心统计图表,能直观呈现数据的中位数、四分位数、离散程度与异常值,是质量控制、实验分 ...
2025-10-28在 CDA(Certified Data Analyst)数据分析师的工作中,“分类变量关联分析” 是高频需求 —— 例如 “用户性别是否影响支付方式 ...
2025-10-28在数据可视化领域,单一图表往往难以承载多维度信息 —— 力导向图擅长展现节点间的关联结构与空间分布,却无法直观呈现 “流量 ...
2025-10-27这个问题问到了 Tableau 中两个核心行级函数的经典组合,理解它能帮你快速实现 “相对位置占比” 的分析需求。“index ()/size ( ...
2025-10-27对 CDA(Certified Data Analyst)数据分析师而言,“假设检验” 绝非 “套用统计公式的机械操作”,而是 “将模糊的业务猜想转 ...
2025-10-27在数字化运营中,“凭感觉做决策” 早已成为过去式 —— 运营指标作为业务增长的 “晴雨表” 与 “导航仪”,直接决定了运营动作 ...
2025-10-24在卷积神经网络(CNN)的训练中,“卷积层(Conv)后是否添加归一化(如 BN、LN)和激活函数(如 ReLU、GELU)” 是每个开发者都 ...
2025-10-24在数据决策链条中,“统计分析” 是挖掘数据规律的核心,“可视化” 是呈现规律的桥梁 ——CDA(Certified Data Analyst)数据分 ...
2025-10-24在 “神经网络与卡尔曼滤波融合” 的理论基础上,Python 凭借其丰富的科学计算库(NumPy、FilterPy)、深度学习框架(PyTorch、T ...
2025-10-23在工业控制、自动驾驶、机器人导航、气象预测等领域,“状态估计” 是核心任务 —— 即从含噪声的观测数据中,精准推断系统的真 ...
2025-10-23在数据分析全流程中,“数据清洗” 恰似烹饪前的食材处理:若食材(数据)腐烂变质、混杂异物(脏数据),即便拥有精湛的烹饪技 ...
2025-10-23在人工智能领域,“大模型” 已成为近年来的热点标签:从参数超 1750 亿的 GPT-3,到万亿级参数的 PaLM,再到多模态大模型 GPT-4 ...
2025-10-22在 MySQL 数据库的日常运维与开发中,“更新数据是否会影响读数据” 是一个高频疑问。这个问题的答案并非简单的 “是” 或 “否 ...
2025-10-22在企业数据分析中,“数据孤岛” 是制约分析深度的核心瓶颈 —— 用户数据散落在注册系统、APP 日志、客服记录中,订单数据分散 ...
2025-10-22在神经网络设计中,“隐藏层个数” 是决定模型能力的关键参数 —— 太少会导致 “欠拟合”(模型无法捕捉复杂数据规律,如用单隐 ...
2025-10-21在特征工程流程中,“单变量筛选” 是承上启下的关键步骤 —— 它通过分析单个特征与目标变量的关联强度,剔除无意义、冗余的特 ...
2025-10-21在数据分析全流程中,“数据读取” 常被误解为 “简单的文件打开”—— 双击 Excel、执行基础 SQL 查询即可完成。但对 CDA(Cert ...
2025-10-21在实际业务数据分析中,我们遇到的大多数数据并非理想的正态分布 —— 电商平台的用户消费金额(少数用户单次消费上万元,多数集 ...
2025-10-20在数字化交互中,用户的每一次操作 —— 从电商平台的 “浏览商品→加入购物车→查看评价→放弃下单”,到内容 APP 的 “点击短 ...
2025-10-20