接着上一篇的内容,接下来分析下公司行业背景的数量分布
3.2 公司行业分布情况
def sub(x):
return re.sub(r'、| ', ',', x)
df['公司行业'] = df['公司行业'].apply(sub)
原数据中行业分布,有些公司用、代替了,作为分隔符,所以需要用上面的自定义函数来做替换
由于每个公司可能会有不止一个行业背景,所以需要拆分并合并到原表中
def split_data(data, colname, sp=',', rename='行业'):
tmp = data[colname].str.split(sp, expand=True)
r = tmp.stack().reset_index(level=1, drop=True)
r = r.to_frame()
r.columns = [rename]
r.dropna()
result = data.join(r)
return result.dropna(subset=[rename])
r = split_data(df, '公司行业', sp=',')
这是拆分之后的表r
接下来对r表进行分组统计数量就可以
tmp5 = r.groupby('行业')
tmp5 = tmp5.size()
分组之后显示如下图
用上文中自定义的函数get_values()来获取可视化所需的x,y轴数据
xindex, vals = get_values(tmp5)
pie = Pie('公司行业分布', height=700, width=1100)
pie.add('', xindex, vals, is_label_show=True, legend_pos='90%',
radius=[20,75], rosetype='area')
pie
可以在图中看到,移动互联网行业占据了超过1/3的比例,所以选择数据分析行业的话,朝移动互联网行业进军是个不错的选择,每天大量的app活跃,需要一定的数据支撑;而金融和数据服务行业紧随其后,不过这两个的业务知识水平要求较高;电商的比例并不高,可能是因为需求数据分析的电商品牌本身不多,亦或是许多分析工作偏财务类,由其他岗位负责。
3.3:薪资和工作经验的关系,箱状图
在源数据中筛选出薪资和工作经验两列,用seaborn箱状图绘图即可
tmp = df.filter(items=['所需资历','平均薪资 单位:k'])
plt.figure(figsize=(10,5))
sns.boxplot(x='所需资历', y='平均薪资 单位:k', data=tmp)
上图可发现,5-10年资历所给出的薪资明显高于其他;而1年以下的上下限都很低,甚至不如应届毕业生;1年以上经验的,大部分薪资都过1w了,算是过了及格线;整体分布符合以往经验,资历越高,期望薪资越高。
3.4:教育背景的分布情况以及与薪资之间的关系
薪资除了和工作经验有关,当然也会和教育背景有所关联,我们先通过饼图来直观看出,教育背景在数据分析岗位上的需求分布
tmp = df.filter(items=['教育程度','平均薪资 单位:k'])
result = tmp.groupby('教育程度')
r = result.size()
xindex, vals = get_values(r)
pie = Pie('教育程度分布情况', height=500, width=800)
pie.add('', xindex, vals, is_label_show=True, legend_pos='90%',
radius=[0,75])
pie
本科占据绝大部分的要求,即大多数求职者都能满足,除去一个异常值,需要博士文凭,本科以上文凭占比只有6%不到,因此可以说,数据分析岗位对教育背景的门槛并不高。
了解完教育背景分布情况后,我们可以来分析下不同教育背景下,薪资的趋势是如何的:
result = tmp.groupby('教育程度')
result = result['平均薪资 单位:k'].agg([('平均薪资', 'mean'),('最高薪资',max),('最低薪资',min)])
def convert_f(x):
return '%.2f' % x
result['平均薪资'] = result['平均薪资'].apply(convert_f)
result
上面的代码目的是根据教育背景来分组,计算拉勾网给出的最高、最低以及上一篇计算出的平均薪资。
将数据准备好后,就可以可视化了,这回我们用pyecharts中的折线图Line进行绘制:
from pyecharts import Line
xindex = result.index.values
line = Line('薪资与教育背景')
lcolors = (x for x in ['yellow', 'green', 'red'])
for col in result.columns:
line.add(col, xindex, result[col].values, line_color=next(lcolors), yaxis_formatter='k')
line
图中我们可以看到除去异常值的博士文凭,代表“平均薪资”的黄色线,不限、本科和硕士几乎没有差距,而大专的平均薪资相对比较低;比较有意思的点是,最高薪资,本科可以达到60k,而硕士比不限还要低,结合上面的教育背景分布饼图,有可能许多HR对教育背景没有太多的限制,达到本科即可,所以即使是需要相当经验和知识水平的岗位,HR所给的教育背景依旧是本科。
3.5:不同工作经验下,教育背景和平均薪资的走势
既然根据上面的图中,我们可以看到工作经验和教育背景这两个因素,都对平均薪资有所影响,所以接下来我们来分析下不同工作经验下,教育背景和平均薪资的走势:
result = df[df['所需资历'] != '不限']
tmp = result.filter(items=['所需资历','教育程度','平均薪资 单位:k'])
# 将x轴数据进行排序,增加可读性
x = ['应届毕业生', '1年以下', '1-3年', '3-5年', '5-10年', '10年以上']
def sort_index2(data, x, colname='c'):
list_custom = x
data[colname] = data.所需资历
data[colname] = data[colname].astype('category')
data[colname].cat.reorder_categories(list_custom, inplace=True)
data.sort_values(colname, inplace=True)
result = data.drop(colname, axis=1)
return result
data = sort_index2(tmp, x)
data
将x轴坐标排序搞定后,可以进行可视化操作了,使用seaborn的pointplot来显示趋势:
hue_order = ['不限','大专','本科','硕士']
plt.figure(figsize=(10,5))
plt.title('不同工作经验下,教育背景和平均薪资的走势', pad=20, fontsize=20, color=sns.xkcd_rgb['reddish'])
plt.ylabel('平均薪资 单位:k',labelpad=10, fontsize=12, color=sns.xkcd_rgb['reddish'])
plt.xlabel('所需资历', labelpad=10, fontsize=12, color=sns.xkcd_rgb['reddish'])
sns.pointplot(x='所需资历', y='平均薪资 单位:k', hue='教育程度', data=data, ci=0, palette='tab20b_r', hue_order= hue_order)
可以看到,基本不管是何教育程度,薪资水平都是随着工作经验的上升而上升;而在相同工作经验下,也是教育程度越高,薪资越高,符合我们的常识。
3.6:数据分析师技能标签
最后,我们来看下,作为数据分析师,到底哪些技能标签,是最为公司所看重和需要的?
tmp = df.filter(items=['技能标签'])
# 和公司行业背景一样,技能标签较多,所以需要拆分
def split_data(data, colname, sp=',', rename='技能'):
tmp = data[colname].str.split(sp, expand=True)
r = tmp.stack().reset_index(level=1, drop=True)
r = r.to_frame()
r.columns = [rename]
r.dropna()
result = data.join(r)
return result.dropna(subset=[rename])
# 看数据可以发现,拉勾网爬取下来的技能标签是带有单引号的,所以需要去除
def find_str(x):
return re.search(r"'([\S\s]+?)'", x).group(1)
tmp2 = split_data(tmp, '技能标签')
tmp2 = tmp2.filter(items=['技能'])
tmp2 = tmp2[tmp2['技能'] != '[]']
tmp2 = tmp2.applymap(find_str)
tmp2
数据处理好后,可以利用pyecharts中的WordCloud来进行词云绘图:
from pyecharts import WordCloud
result = tmp2.groupby('技能')
result = result.size()
xindex, vals = get_values(result)
word = WordCloud('数据分析技能标签词云', height=500, width=900)
word.add('', xindex, vals, shape='star', word_gap=35, word_size_range=[20,80])
word
从图中我们可以看到,基本的数据分析的能力是最为重要的,其次SQL语法也相当关键,因为数据分析的自主取数工作也是尤为重要的;BI作为商业智能可视化,也是顺应市场潮流;数据挖掘作为数据分析的更深层次技术,各种模型的建立对数据的分类、聚类、预测等有很重要的作用。
3.7:回归图分析
最后的最后,既然上图看出了所需资历和平均薪资,是呈现一个正相关的,那么到底是否相关,相关程度如何,还是需要用简单的一元线性回归图来看一下:
# 将每个所需资历转换成间距相同的可计算的离散数值
dic = {'应届毕业生':1, '1年以下':2, '1-3年':3, '3-5年':4, '5-10年':5, '10年以上':6}
def resample_to_numeric(x):
for y in dic.keys():
if x == y:
return dic[y]
data['所需资历'] = data.所需资历.apply(resample_to_numeric)
data
数据分整理完后用seaborn.lmplot进行作图:
from scipy import stats
g = sns.jointplot(x='所需资历', y='平均薪资 单位:k', data=data, kind='reg', color=sns.xkcd_rgb['cool blue'])
g.annotate(stats.pearsonr)
g.savefig('所需资历和平均薪资关系-lmplot.png')
可以看到皮尔逊相关系数是0.66,p值<.05,所以可信度较高,的确薪资和资历是呈现一种正相关的。而通过x轴和y轴边的密度函数图也能发现,所需资历集中在3和4,也就是我们自己定义的1-3和3-5年这两个区间;而平均薪资集中于15k上下。
结语:
至此,从爬取数据,到基本内容的数据分析,本项目告一段落,由于最后的最后通过回归图发现了相关性,所以后续可以用机器学习中的线性回归模型来更深入研究下平均薪资这个因变量与教育背景和工作经验这两个自变量之间,到底有多强的相关性。