對于非計算機專人士,大多數統計就是計數,而且許多基礎的Hadoop作業都包含了計數過程。我們希望從專利引用數據集中得到專利被引用的次數。這同樣是計數。期望的輸出結果如下:
專利號 出現次數
10000 1
100000 1
1000006 1
1000007 1
1000011 1
1000017 1
1000026 1
1000033 2
1000043 1
1000044 1
1000045 1
1000046 2
1000049 1
1000051 1
1000054 1
1000065 1
1000067 3
在每個記錄中,專利號與引用次數相關聯。我們可以為此寫一個MapReduce程序。如果有一個類似方式處理數據的MapReduce程序,你就可以復制并修改它使之符合你的要求。
我們已經有了一個獲得反向引用索引的程序。可以修改這個程序來輸出技術結果,而不是一個專利引用列表。我們只需修改Reducer。如果我們選擇讓技術結果輸出類型為IntWritable,就需要在Reducer代碼的3個地方進行聲明。在以前的注視著我們稱它們為V3
public void reduce(IntWritable key, Iterator<IntWritable> values,OutputCollector<IntWritable, IntWritable> output,Reporter reporter) throws IOException
{
int count =
0;
while (values.hasNext()){count += values.next().
get();}output.collect(key,
new IntWritable(count));
}
}
通過修改幾行代碼并匹配好類型,我們就有了一個新的MapReuce程序。這個程序看上去做的修改很少。讓我們再看一個修改較多的例程,不過它依然保留了MapReduce基礎程序的結構。
運行前面的例子后,我們現在得到了一個數據集,包含了對每個專利的引用次數的統計。要想做好一個很好地練習,可以對這些統計值再做統計。讓我們生成一個引用計數的直方圖。我們預計會看到一個有趣的引用計數分布,即大多數專利僅被引用一次,而少部分被引用上百次。
編寫MapReduce程序第一步就是了解數據流。當mapper讀取一個記錄時,它忽略專利號并輸出一個鍵值對
public class CitationHistogram extends Configured implements Tool
{public static class MapClass extends MapReduceBase implementsMapper<Text, Text, IntWritable, IntWritable>{private final static IntWritable uno =
new IntWritable(
1);
private IntWritable citationCount =
new IntWritable();
public void map(Text key, Text value,OutputCollector<IntWritable, IntWritable> output,Reporter reporter) throws IOException{citationCount.set(Integer.parseInt(value.toString()));output.collect(citationCount, uno);}}
public static class Reduce extends MapReduceBase implementsReducer<IntWritable, IntWritable, IntWritable, IntWritable>{@Override
public void reduce(IntWritable key, Iterator<IntWritable> values,OutputCollector<IntWritable, IntWritable> output,Reporter reporter) throws IOException{
int count =
0;
while (values.hasNext()){
count += values.next().get();}output.collect(key,
new IntWritable(
count));}}@Override
public int run(String[] args) throws Exception{Configuration conf = getConf();JobConf job =
new JobConf(conf, CitationHistogram.class);Path in =
new Path(args[
0]);Path out =
new Path(args[
1]);FileInputFormat.setInputPaths(job, in);FileOutputFormat.setOutputPath(job, out);job.setJobName(
"CitationHistogram");job.setMapperClass(MapClass.class);job.setReducerClass(Reduce.class);job.setInputFormat(KeyValueTextInputFormat.class);job.setOutputFormat(TextOutputFormat.class);job.setOutputKeyClass(IntWritable.class);job.setOutputValueClass(IntWritable.class);JobClient.runJob(job);
return 0;}
public static void main(String[] args) throws Exception{
int res = ToolRunner.run(
new Configuration(),
new CitationHistogram(),args);System.out.println(res);}}
現在類名為CitationHistogram,新的名字將替換程序中所有Myjob相關的部分。Main()方法基本相同。Driver幾乎沒有改變。輸入格式和輸出格式任然分別為KeyValueTextInputFormat和TextOutPutFormat。主要的變化在輸出的鍵和值的類,它們現在改為IntWritable來匹配K2和V2的新類型。我們還去掉了這一行:
job.set(“key.value.separator.in.input.line”,”,”);
它用于設置KeyValueTextInputFormat所采用的分隔符,把每個輸入行劃分為一個鍵值對。以前使用逗號來處理原始的專利引用數據。這里不對這個屬性進行設置,分隔符默認采用制表符,它適合于分隔引用技術數據。
public class MapClass extends MapReduceBase implements Mapper<Text, Text, IntWritable, IntWritable>
{private final static IntWritable uno =
new IntWritable();
private IntWritable citationCount =
new IntWritable();@Override
public void map(Text key, Text value,OutputCollector<IntWritable, IntWritable> output, Reporter reporter)throws IOException{citationCount.set(Integer.parseInt(value.toString()));output.collect(citationCount, uno);}}
Map()方法中多出了一行,用于設置citationCount做類型轉換。出于對效率的考慮,citationCount和uno的定義被放在類中而不是方法中。有多少記錄,map()方法就會被調用多少次(對每個JVM而言,就是一個分片中的記錄數)。減少在map()方法中生成對象的個數可以提高性能,并減少垃圾回收。由于citationCount和uno被傳遞給output.collect(),我們依賴output.collect()方法的約定不會修改這兩個對象。
轉載于:https://www.cnblogs.com/ainima/p/6331860.html
總結
以上是生活随笔為你收集整理的MapReduce实现计数的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。