说我有一个输入文件,如下所示
dept_id emp_id salary
1 13611 1234
2 13609 3245
3 13612 3251
2 13623 1232
1 13619 6574
3 13421 234
现在我想找到每个部门的平均工资。像下面的Hive查询一样:
SELECT dept_id, avg(salary) FROM dept GROUP BY dept_id
这将返回输出:
dept_id avg_sal
----------------
1 3904.0
2 2238.5
3 1742.5
现在,我想要做的是生成相同的输出,但使用mapreduce框架。那怎么写呢?提前谢谢!
答案 0 :(得分:2)
重要:强> 在尝试实现之前,首先尝试MapReduce中的一些基本示例,如实现字数统计程序,理解逻辑,甚至在此之前,阅读有关MapReduce如何工作的书籍或教程。
聚合内容(如查找平均值)的想法是,您在映射阶段按键(部门ID)进行分组,然后在减少阶段减少特定部门的所有工资。
以更正式的方式:
<强> MAP:强>
输入:表示工资记录的行(即dep_id,emp_id,salary)
输出(键,值):( dep_id,salary)
<强> REDUCE:强>
输入(键,值):( dep_id,工资:具有此dep_id的工资值列表)
输出(键,值):( dep_id,avg(工资))
这样,属于同一部门的所有工资都将由同一个减速机处理。你需要在reducer中做的就是找到输入值的平均值。
答案 1 :(得分:2)
代码----
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class AverageSalary {
public static class AvgMapper
extends Mapper<Object, Text, Text, FloatWritable>{
private Text dept_id = new Text();
private FloatWritable salary = new FloatWritable();
public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {
String values[] = value.toString().split("\t");
dept_id.set(values[0]);
salary.set(Float.parseFloat(values[2]));
context.write(dept_id, salary);
}
}
public static class AvgReducer
extends Reducer<Text,FloatWritable,Text,FloatWritable> {
private FloatWritable result = new FloatWritable();
public void reduce(Text key, Iterable<FloatWritable> values,
Context context
) throws IOException, InterruptedException {
float sum = 0;
float count = 0;
for (FloatWritable val : values) {
sum += val.get();
count++;
}
result.set(sum/count);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "average salary");
job.setJarByClass(AverageSalary.class);
job.setMapperClass(AvgMapper.class);
job.setCombinerClass(AvgReducer.class);
job.setReducerClass(AvgReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(FloatWritable.class);
FileInputFormat.addInputPath(job, new Path("/home/kishore/Data/mapreduce.txt")); // input path
FileOutputFormat.setOutputPath(job, new Path("/home/kishore/Data/map3")); // output path
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
output
1 3904.0
2 2238.5
3 1742.5
答案 2 :(得分:0)
如果您尚未完成任何培训计划,请访问edureka上的免费视频,以便更好地理解概念:Map Reduce
映射
映射器将输入键/值对映射到一组中间键/值对。
地图是将输入记录转换为中间记录的各个任务。转换后的中间记录不需要与输入记录的类型相同。给定的输入对可以映射到零个或多个输出对。
减速
Reducer将一组中间值减少到一个较小的值集合。
作业的减少次数由用户通过Job.setNumReduceTasks(int)设置。
Apache Hadoop网站上的工作示例:Word Count example
对于您的用例,简单使用单词计数示例是不够的。 您必须在Mapper上使用Combiner和分区器,因为您使用的是Group by。访问此视频:Advanced Map reduce