确定目标
- 简单分析数据分析相关岗位的薪酬状况及技能要求;
- 尝试数据分析从数据获取到数据分析报告撰写的整个数据分析流程,学习爬虫、数据清洗、数据分析相关技巧。
数据获取
获取的岗位数据来源于某招聘网站,采取爬虫的方式获取,岗位搜索的关键词为:“数据分析”,爬取的信息包括:岗位名称,城市,薪酬,学历要求,经验要求,岗位描述/职责,分五次爬取,爬取了北京、上海、广州、深圳、南京五个城市的岗位数据共1472条
数据清洗
在清洗之前,我已经将爬取的北京、上海、广州、深圳、南京的数据合并为一个excel文件,以下直接读取(使用read_csv时出现错误,可能是因为岗位职责/描述一栏,数据本身就包含逗号的缘故,故使用read_excel),这次数据清洗主要使用pandas库,的清洗工作包括:
- 删除无效的列和行,增加索引列
- 对薪酬列进行分割,分为最低薪酬salary_min和最高薪酬salary_max,去除无关字符
- 工作经验列划分类别:应届毕业生、一年以下、1-3年、3-5年、5-10年、10年以上,去除无关字符
- 学历列划分类别:大专、本科、硕士、博士
- 岗位职责/描述列去除无关字符
数据清洗代码如下:
from pandas import Series,DataFrame
import pandas as pd#读取文件
parsed = pd.read_excel('C:/Users/King/Desktop/拉勾网数据分析/拉勾网数据.xlsx', names = ['position','company','salary','city','expe','edu','desc'])#新增列(后面作为索引),删除‘公司’列
parsed = parsed.reindex(columns = ['seq','position','salary','city','expe','edu','desc'])#删除无关的行,指定索引列并赋值
parsed = parsed[~(parsed['position'].isin(['职位']))]
parsed['seq'] = range(parsed.iloc[:,0].size)
parsed.set_index(['seq'],inplace=True)#薪酬列分割为salary_min和salary_max
salary_m = parsed['salary'].str.replace('k','').str.replace('K','').str.split('-', expand = True)
parsed = parsed.drop('salary', axis = 1).join(salary_m)
parsed.rename(columns = {0:'salary_min',1:'salary_max'}, inplace=True)#经验列统一类别
expe_m = parsed['expe'].str.strip('经验年').str.replace('不限','应届毕业生')
parsed = parsed.drop('expe', axis = 1).join(expe_m)#学历列统一类别
edu_c = parsed['edu'].str.replace(r'.*不限.*','大专').str.replace(r'及以上.*','')
parsed = parsed.drop('edu', axis = 1).join(edu_c)#岗位职责列去除无关字符
desc_c = parsed['desc'].str.replace(r'[\n,"岗位职责","职位描述","职责描述","工作职责",":"]','')
parsed = parsed.drop('desc',axis = 1).join(desc_c)
清洗后的数据预览如下图:
数据简单分析
这次采集的数据维度较少,仅进行简单的分析,不涉及高深的统计学理论
基本描述
代码如下:
#获取不同城市的岗位数量
city_num = parsed['city'].value_counts()
city_s = city_num.index.tolist()
num_s = [i for i in city_num]#获取不同经验段岗位的数量
expe_num = parsed['expe'].value_counts()
expe_e = expe_num.index.tolist()
num_e = [i for i in expe_num]#开始画图
from pyecharts import Grid,Bar,Piebar = Bar('各城市岗位数量',title_pos='50%')
bar.add('城市',city_s,num_s, mark_point = ['max','min'],legend_pos="70%")bar_expe = Bar('各经验段岗位数量')
bar_expe.add('经验要求/年',expe_e,num_e,xaxis_rotate=30,mark_point = ['average'],legend_pos="20%")pie = Pie("各经验段岗位数量占比",title_top="50%")
pie.add("", expe_e, num_e, is_random=True,center = ['25%',"75%"],radius=["10%", '25%'], rosetype="area", is_legend_show=False,is_label_show=True)pie_c = Pie('各城市岗位数量占比',title_top="50%", title_pos="50%")
pie_c.add("", city_s, num_s, is_random=True,center = ['75%','75%'],radius=['10%', '25%'], rosetype="area", is_legend_show=False,is_label_show=True)grid = Grid(height = 800, width = 950)
grid.add(bar, grid_left="60%", grid_bottom = '60%')
grid.add(bar_expe, grid_right="60%", grid_bottom = "60%")
grid.add(pie_c, grid_right = '60%', grid_top = "60%")
grid.add(pie, grid_left = "60%", grid_top = "60")
grid
以上,一共采集了1472条数据分析相关岗位的信息。从城市分布来看,北京和上海的均为450条,并不是因为这两个城市仅有450个数据分析相关岗位,而是因为该招聘网站只显示前450条招聘信息,爬虫爬到450条时便停止了,该招聘网站上,深圳和广州的岗位数量较北上少,南京最少,仅有35条数据分析相关岗位的招聘信息。
从要求的工作经验来看,大部分企业的需求仍然是有工作经验的数据分析师,招聘一年以下工作经验(含应届毕业生)的仅占16.5%,企业都想招进来就能直接上手的,而学校开设数据科学相关专业也只是近两年的事,很少应届生能够直接满足企业的需求;招聘1-5年工作经验占比70%以上,到10年以上工作经验仅有2条岗位信息,这也是因为数据分析师近几年才发展起来的职业,能有十年以上数据科学相关工作经验的职业人员本身就很少。
对比分析
城市-薪酬
先使用pyecharts库绘制箱线图,代码如下:
#获得数据,绘制箱线图
from pyecharts import Boxplot#城市数据,作为x轴
x_axis = '北京,上海,广州,深圳,南京'.split(',')#获得最低和最高薪酬组的数据,作为y轴数据
parsed['salary_min'] = parsed['salary_min'].astype(int)
parsed['salary_max'] = parsed['salary_max'].astype(int)
ls_min = []
ls_max = []
for x in x_axis:lt_min = parsed[parsed['city'] == x]['salary_min'].tolist()ls_min.append(lt_min)lt_max = parsed[parsed['city'] == x]['salary_max'].tolist()ls_max.append(lt_max)#开始绘制
boxplot = Boxplot('各城市最低和最高工资的箱线图')
boxplot.add('最低薪酬',x_axis, boxplot.prepare_data(ls_min))
boxplot.add('最高薪酬',x_axis, boxplot.prepare_data(ls_max))
boxplot
效果如下
可以看到pyecharts绘制箱线图默认没有排除离群点的影响,由于没有找到设置的相关参数,因此转用matplotlib,matplotlib绘制代码和效果如下:
import matplotlib.pyplot as plt
import matplotlib
#设置以保证中文显示不出问题
matplotlib.rcParams['font.family'] = 'STSong'
matplotlib.rcParams['font.size'] = 15
#开始画图
parsed.boxplot(column=['salary_min','salary_max'], by='city',figsize = (10,5))
plt.savefig('各城市之间薪酬的差异.jpg', dpi=600)
plt.show()
这里主要从不同城市的最低薪酬(左边)和最高薪酬(右边)两个角度进行分析。最低薪酬的平均水平来看,北京、上海、深圳的几乎在同一水平,广州和南京的略低一些,整体来看,最低均在20K以下;从最高薪酬来看,波动明显比最低薪酬大得多,最大值出现在广州,达到了100k,平均水平来看,北京、上海、深圳均在20k左右及以上,而广州和南京的大部分仍在20k以下。
学历-薪酬
lables = ['','大专','本科','硕士','博士']
parsed_edu = parsed[['salary_min','salary_max','edu']].copy()
ls_new = parsed_edu['edu']
#改名字很重要
ls_new.name = 'edu_num'
for i in range(4):ls_new = ls_new.str.replace(lables[i + 1], str(i))
parsed_edu = parsed_edu.join(ls_new.astype(int))
parsed_edu = parsed_edu.sort_values(by = 'edu_num')
#画图
parsed_edu.boxplot(column=['salary_min','salary_max'], by='edu_num',fontsize = 14, figsize = (10,5))
plt.xticks(range(7),lables)
plt.savefig('各不同学历之间薪酬的差异.jpg', dpi=600)
plt.show()
最低薪酬来看,大专的平均薪酬水平最低,本科和硕士差不多,博士学历的波动最小、最低薪酬也在15k以上,这也说明大专到本科是一个小分水岭、硕士到博士是一个大分水岭当然这也有,而本科和硕士的基本差不多;最高薪酬来看,大专学历的薪酬水平整体上较其余学历略低,本科和硕士依旧相差不大,奇怪的是博士的最高薪酬差强人意。
这里有一个重要原因是这次采集数据采用的搜索关键字是‘数据分析’,而对大部分企业而言,他们的数据分析工作并不需要博士学历,因此此次仅采集到3个招聘博士的岗位信息(如下图所示),不具有代表性。
工作经验-薪酬
lables = ['','应届毕业生','1年以下','1-3','3-5','5-10','10年以上']
parsed_expe = parsed[['salary_min','salary_max','expe']].copy()
ls_new = parsed_expe['expe']#一定要改名字
ls_new.name = 'expe_num'
for i in range(6):ls_new = ls_new.str.replace(lables[i + 1], str(i))
parsed_expe = parsed_expe.join(ls_new.astype(int))
parsed_expe = parsed_expe.sort_values(by = 'expe_num')
#画图
parsed_expe.boxplot(column=['salary_min','salary_max'], by='expe_num',rot = 30,fontsize = 14, figsize = (10,5))
plt.xticks(range(7),lables)
plt.savefig('各不同工作经验段之间薪酬的差异.jpg', dpi=600)
plt.show()
与学历相比,不同工作经验带来的薪酬差距要大得多,无论从最低薪酬还是最高薪酬来看,都能看到薪酬随工作经验的明显递增趋势,特别是工作3-5年后,薪酬增长速度较快。如下图所示,这里要求10年以上工作经验的岗位仅有2个,因此也不具有代表性。
岗位需求分析
import jieba
import re#转成字符串格式,并将所有字母转化为大写,方便分析
t = ''.join(parsed['desc'].tolist())
t = t.upper()#清除无关内容(序号、特殊符号等)
pattern = re.compile(r'\d[.|\.|、]')
pattern1 = re.compile(r'\s')
t = re.sub(pattern,'', t)
t = re.sub(pattern1, '', t)
for ch in '!"#$%&()*+,-./:;<=>?@[\\]^_‘{|}~【】◆,;、。()':t = t.replace(ch, "")
t = t.replace('\xa0','')#使用jieba库分词
words = jieba.lcut(t)
counts = {}
for word in words: counts[word] = counts.get(word,0) + 1#给分词字典添加技能类词汇,方便识别
ls_add = 'SQL,PYTHON,SPSS,TABLEAU,OFFICE,EXCEL,PPT,HADOOP,JAVA,R,SAS,SPARK,HIVE,WORD,ABTEST,MYSQL,MATLAB'.split(',')
for i in ls_add:jieba.add_word(i)#不断调整,删除无关字符
excludes = {'的','和','等','有','数据','分析','及','及','对','并','数据分析','相关','优先','能力','进行','与','熟悉','要求','使用','需求','团队','以上','负','熟练','或','良好','以上学历','年','公司','为','任','专业','具备','能','提供','具有','项目','互联网','者','支持','挖掘','模型','建模','能够','强','具','统计','开发','了解','监控','设计','大','中','应用','指标','建议','建立','客户','根据','完成','通过','研究','体系','管理','行为','技术','平台','部门','较','提出','参与','较','较强','软件','3','推动','掌握','基于','一定','理解','从','精通','合','2','至少','包括','发展','协助','搭建','一种','语言','优秀','资格','以及','在','各','熟练掌握','常用','处理','深入','落地','敏感度','结果','发现','方向','日常','数据处理','1','善于','指定','流程','精神','机器','快速','提升','方法','海量','系统','敏感','制定','其他','核心','各类','整理','建设','构建','协','输出','定期','完善','基础','提取','有效','实现','信息','方案','我们','运用','背景','针对','解决','活动','深度','你','如','结合','专业本科','解决方案','领域','给出','改进','专题','维护','驱动','跟踪','及时','编写','形成','规划','场景','考虑','实际','新','框架','任心','操','清晰','实施','5','机会','可','将','情况','类','特征'}
for word in excludes:del counts[word]
以上是使用jieba库分词,清除无关的字符等,下面绘制招聘需求里高频词汇的词云。
#绘制招聘需求里高频词汇的词云
words = []
counts_1 = []
for i in range(60):word, count = items[i]words.append(word)counts_1.append(count)
from pyecharts import WordCloud
wordcloud = WordCloud(width=700, height=500)
wordcloud.add("", words, counts_1, word_size_range=[20, 100])
wordcloud
提取1472条招聘岗位的岗位说明信息中的高频词汇,绘制的词云图如上。可以明显看到‘业务’、‘产品’、‘运营’、‘经验’、‘沟通’、‘用户’、‘行业’、‘报告’等字眼,可以看出:
- 数据分析这个岗位和业务是分不开的,数据分析是为业务提供支持的,也正因此,企业更愿意招聘有工作经验的,因为相对应届毕业生而言,他们有更强的业务理解能力,这也告诉我们不要陷入一味地学习技能的陷阱里,平时也要多关注行业信息、多接触业务,培养自己的业务理解能力、逻辑思维能力
- 很多公司的数据分析师的职能和产品、运营没有清楚的界限,通常一个数据分析师也充当了产品经理、运营人员的角色,因此也会有很好的沟通能力、表达能力方面的要求,在选择工作的时候一定要看清这个公司的数据分析师到底是做什么的
接下来在看现在企业招聘数据分析师一般要求哪些技能:
ls_add = 'SQL,PYTHON,SPSS,TABLEAU,OFFICE,EXCEL,PPT,HADOOP,JAVA,R,SAS,SPARK,HIVE,WORD,ABTEST,MYSQL,MATLAB'.split(',')
ls_num = []
for i in ls_add:ls_num.append(t.count(i))
ls = list(zip(ls_add, ls_num))
ls.sort(key = lambda x:x[1],reverse=True)
ls_tec,ls_count = zip(*ls)
ls_count#统计各技能出现的频次,绘制条形图
bar1 = Bar("技能需求条形图")
bar1.add("", ls_tec[1:], ls_count[1:],xaxis_rotate= -30 , is_label_show=True,is_datazoom_show=True,datazoom_type="both", datazoom_range=[7, 16])
bar1
对招聘的技能要求进行提取【注意:这里将R排除了,因为没能成功有效统计R技能需求的实际岗位数量】,可以看到:
- SQL依旧是数据分析师的基础必备技能,被提及次数最多
- python略微超过excel,说明python也逐渐受到数据分析师的重视,但是excel仍然是职场必备技能之一
- 大数据工具Hadoop、Spark,说明部分企业的数据分析师也兼大数据的相关工作
- 可视化工具Tableau正在逐渐受到重视
最后,再给出一个使用Jupyter完成整个流程的截图: