用MapReduce对招聘数据处理分析+可视化
mapreduce处理数据并用python可视化
对招聘数据处理分析并可视化
前言
关于本次任务:
当我们择业,寻找工作时,需要从各大招聘平台,招聘网站以及招聘单位官网等获取招聘信息,那么对相关数据进行分析,能帮助我们更好的了解招聘市场情况,可以对我们的就业提供参考。本次任务从Boss直聘获取数据,分析热门职位,城市平均工资等信息,帮助我们更好地面对严峻的就业形势。
以下是本次任务主要内容:
一、数据源和任务目标
数据来源于Boss直聘,一共1651条记录,其中包含id,city(城市),education(学历),salary(工资)等12个属性,数据样式如下:
任务目标:
1.各学历平均工资;
2.各城市平均工资走势;
3.各岗位招聘数量占比分析
二、具体实现
任务1.各学历平均工资
涉及数据属性:education, salary
任务输入:data.txt
任务输出:output/01/part-r-00000
总体流程设计如图:
数据处理:
Map部分
public static class Map extends Mapper<LongWritable, Text, Text, Text> {
Text k = new Text();
Text v = new Text();
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String s = value.toString();
if (!s.contains("advantage") && s.trim().length() > 0 && s.split("\t").length == 12) {
String[] strings = s.split("\t");
k.set(strings[3]);
v.set(strings[8]);
context.write(k, v);
}
}
}
Reduce部分
public static class Reduce extends Reducer<Text, Text, Text, Text> {
Text v = new Text();
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
Double sumSalary = 0D;
int cntSalary = 0;
for (Text value : values) {
int salary = Integer.parseInt(value.toString());
sumSalary += salary;
cntSalary ++;
}
double avgSalary = sumSalary / cntSalary;
v.set(avgSalary+"");
context.write(key, v);
}
}
可视化:
def drawChart_1():
root = "output/01/part-r-00000"
date = []
cases = []
with open(root, 'r',encoding='utf-8') as f:
while True:
line = f.readline()
if not line:
break
strings = line.split('\t')
date.append(str(strings[0]))
cases.append(int(float(strings[1])))
d = (
Bar()
.add_xaxis(date)
.add_yaxis("平均工资", cases, stack="stack1")
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(title_opts=opts.TitleOpts(title="各学历平均工资"))
.render("output_html/result1.html")
)
运行结果:
通过数据分析以及观察可视化效果,各学历层次工资金额都很可观,博士生尤为显著,除此以外,大专,本科,硕士三个学历层次工资金额随学历层次的升高而增加。而对于其他层次,例如自考,培训,自学等,其工资水平也并不低,同时在一定程度上反映技术水平的重要性。但从整体来看,正常情况下,学历层次同工资水平是呈正比关系的,同时也反映当下考研热潮的火爆。
任务2.各城市平均工资走势
涉及数据属性:city, salary
任务输入:data.txt
任务输出:output/02/part-r-00000
总体流程设计如图:
数据处理:
Map部分
public static class Map extends Mapper<LongWritable, Text, Text, Text> {
Text k = new Text();
Text v = new Text();
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String s = value.toString();
if (!s.contains("advantage") && s.trim().length() > 0 && s.split("\t").length == 12) {
String[] strings = s.split("\t");
k.set(strings[2]);
v.set(strings[8]);
context.write(k, v);
}
}
}
Reduce部分
public static class Reduce extends Reducer<Text, Text, Text, Text> {
Text v = new Text();
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
Double sumSalary = 0D;
int cntSalary = 0;
for (Text value : values) {
int salary = Integer.parseInt(value.toString());
sumSalary += salary;
cntSalary ++;
}
double avgSalary = sumSalary / cntSalary;
v.set(avgSalary+"");
context.write(key, v);
}
}
可视化:
def drawChart_2():
root = "output/02/part-r-00000"
date = []
cases = []
with open(root, 'r',encoding='utf-8') as f:
while True:
line = f.readline()
if not line:
break
strings = line.split('\t')
date.append(str(strings[0]))
cases.append(int(float(strings[1])))
(
Line(init_opts=opts.InitOpts(width="1600px", height="800px"))
.add_xaxis(xaxis_data=date)
.add_yaxis(
series_name="工资",
y_axis=cases,
markpoint_opts=opts.MarkPointOpts(
data=[
opts.MarkPointItem(type_="max", name="最大值")
]
),
markline_opts=opts.MarkLineOpts(
data=[opts.MarkLineItem(type_="average", name="平均值")]
),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="各城市平均工资走势", subtitle=""),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
)
.render("output_html/result2.html")
)
运行结果:
通过数据分析以及观察可视化效果,在各大热门城市中,热门去向依然是北京,上海,广州,深圳(北上广深),工资水平居于第一梯队,是大家争先恐后去发展的地方。除此以外,杭州的平均工资水平也很可观,只是该城市对应届生身份卡得严,更多的是有工作经验的“社会人”在发展,所以很多应届毕业生选择去了工资水平相当的其他热门城市。近年,有很多新一线城市兴起,比如涉及到的南京,成都,武汉,重庆等,其平均工资水平虽然赶不上其他热门地域城市,但对于不少对工资水平要求不是太高,喜欢稍慢一点节奏生活的毕业生也是不错去向。总体来看,除北京,上海,广州,深圳,杭州这些热门城市工资水平在高薪标准以上,其他城市均在其之下。
任务3.各岗位招聘数量占比分析
涉及数据属性:position_name
任务输入:data.txt
任务输出:output/03/part-r-00000
总体流程设计如图:
数据处理:
Map部分
public static class Map extends Mapper<LongWritable, Text, Text, Text> {
Text k = new Text();
Text v = new Text();
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String s = value.toString();
if (!s.contains("advantage") && s.trim().length() > 0 && s.split("\t").length == 12) {
String[] strings = s.split("\t");
k.set(strings[7]);
v.set("1");
context.write(k, v);
}
}
}
Reduce部分
public static class Reduce extends Reducer<Text, Text, Text, Text> {
Text v = new Text();
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
int size = Lists.newArrayList(values).size();
v.set(size+"");
context.write(key, v);
}
}
可视化:
def drawChart_3():
root = "output/03/part-r-00000"
values = []
with open(root, 'r',encoding='utf-8') as f:
while True:
line = f.readline()
if not line:
break
strings = line.split('\t')
values.append([(strings[0]),(strings[1])])
c = (
Pie()
.add("", values)
.set_colors(["orange","red","blue","green"])
.set_global_opts(title_opts=opts.TitleOpts(title="各岗位招聘数量占比分析"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
.render("output_html/result3.html")
)
运行结果:
通过数据分析以及观察可视化效果,可以看出对于数据分析涉及到的这四个岗位:数据分析师,数据挖掘工程师,机器学习工程师,深度学习工程师,其招聘人数占比都差不太多,而其中相比较多的是机器学习工程师和数据挖掘工程师。而随着近年来,大数据,人工智能的发展,对于数据分析,机器学习方面的技术人员需求很大,但同时岗位缺口也很大。
总结
三个任务是对部分招聘数据的分析处理,通过最终的数据分析及结果可视化观察并结合资料可知:
1.学历与工资水平呈正比;
2.北上广深依旧火热,工资水平依旧处于第一梯队;
3.随着近几年大数据、人工智能的崛起。算法类的职位缺口比较大。
以上三点即为最简洁地概括最终处理结果分析。
关于MapReduce:
MapReduce是一个分布式运算程序的编程框架,是用户开发"基于Hadoop的数据分析应用”的核心框架。
MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成-个完整的分布式运算程序,并发运行在一个Hadoop集群上。
其优缺点:
关于优点
- MapReduce易于编程
它简单的实现一些接口,就可以完成一个分布式程序, 这个分布式程序可以分布到大量廉价的PC机器上运行。也就是说你写一个分布式程序,跟写-个简单的串行程序是一模一样的。 就是因为这个特点使得MapReduce编程变得非常流行。
2.良好的扩展性
当你的计算资源不能得到满足的时候,你可以通过简单的增加机器来扩展它的计算能力。
3.高容错性
MapReduce设计的初衷就是使程序能够部署在廉价的PC机器上,这就要求它具有很高的容错性。比如其中一台机器挂了,它可以把上面的计算任务转移到另外一个节点上运行,不至于这个任务运行失败,而且这个过程不需要人工参与,而完全是由Hadoop内部完成的。
4.适合PB级以上海量数据的离线处理
可以实现上千台服务器集群并发工作,提供数据处理能力。
关于缺点
1.不擅长实时计算
MapReduce无法像MySQL-样,在毫秒或者秒级内返回结果。
2.不擅长流式计算
流式计算的输入数据是动态的,而MapReduce的输入数据集 是静态的,不能动态变化。这是因为MapReduce自身 的设计特点决定了数据源必须是静态的。
3.不擅长DAG (有向图)计算
多个应用程序存在依赖关系,后一个应用程序的输入为前一一个的输出。在这种情况下,MapReduce并不是不能做,而是使用后,每个MapReduce作业的输出结果都会写入到磁盘,会造成大量的磁盘IO,导致性能非常的低下。
其核心编程思想:
1)分布式的运算程序往往需要分成至少2个阶段。
2)第一个阶段的MapTask并发实例,完全并行运行,互不相干。
3)第二个阶段的ReduceTask并发实例互不相干,但是他们的数据依赖于上一个阶段的所有MapTask并发实例的输出。
4)MapReduce编程模型只能包含一个Map阶段和一个Reduce阶段,如果用户的业务逻辑非常复杂,那就只能多个MapReduce程序,串行运行。
总结:分析WordCount数据流走向深入理解MapReduce核心思想。
其处理的一般步骤:
用户编写的程序分成三个部分:Mapper、Reducer和Driver
(1)map阶段
用户自定义的Mapr要迷承自己的父类;
Mapper的输入数据是KV对的形式(KV的类型可自定义);
Mapper中的业务逻 辑写在map方法中;
Mape的前出数据是KV对的形式(KV的类型可自定义);
map(方法(MapTasb进程) 对每个<K.V>调用-次。
(2)reduce阶段
用户自定义的Reducer要继承自己的父类;
Reducet的输入数据类型对应Mappe的输出数据类型,也是KV;
Reducer的业务逻辑写在reduce方法中;
ReduceTask进程对每组相同k的<k,v>组调用一 次reduce()方法。
(3)Driver阶段
相当于YARN隼群的客户端,用于提交我们整个程序到YARN集群,提交的是封装了MapReduce程字相关运行参数的job对象。
更多推荐
所有评论(0)