MapReduce程式設計基礎(二)——數值概要(計算最大值、最小值、平均值)
數值概要
數值概要模式是計算資料集聚合統計的一般性模式
適用場景:
要處理的資料數值或者計數
資料可以按某些特定的欄位分組數值概要的應用:
單詞計數
記錄計數
最大/最小值計數
平均值/中位數/標準差
話不多說,現在直接開始我們的第一個示例,最大值、最小值計數示例
最大值、最小值計數示例
1.資料集:
本示例使用Movielens資料集中的u1.base檔案,MovieLens資料集是一個使用者對電影的評分資料集,在後續的示例中我們將一直使用這個資料集,我會將這個資料集上傳到CSDN方便大家下載,檔案的格式如下所示:
第1列到第4列分別代表使用者ID,專案ID,使用者對專案的評分,時間戳
1 1 5 874965758
1 2 3 876893171
1 3 4 878542960
1 4 3 876893119
1 5 3 889751712
1 7 4 875071561
1 8 1 875072484
... .... ....
943 1067 2 875501756
943 1074 4 888640250
943 1188 3 888640250
943 1228 3 888640275
943 1330 3 888692465
2.程式示例
問題:對於給定的使用者專案評分資料,確定每個使用者評分的最大值、最小值、該使用者的評分次數及該使用者的平均評分。
1)自定義Writable型別儲存輸出資料
注意:實現Writable介面必須實現readFields(DataInput in)和write(DataOutput out)方法。定義toString()方法,才能正確解析輸出。
package mapreduce.design.parrerns;
import java.io.*;
import org.apache.hadoop.io.Writable;
/*
* 一個定製的Writable物件類,便於定製特定個數的輸入和輸出
* Writable介面有兩個方法,Write和readFile
* */
public class MinMaxCountTuple implements Writable{
private int min=0;//使用者評過的最低分
private int max=0;//使用者評過的最高分
private double average=0;//使用者的評分
private long count=0;//使用者的評分數
public int getMin(){
return min;
}
public void setMin(int min){
this.min=min;
}
public int getMax(){
return max;
}
public void setMax(int max){
this.max=max;
}
public double getAverage(){
return average;
}
public void setAverage(double average){
this.average=average;
}
public long getCount(){
return count;
}
public void setCount(long count){
this.count=count;
}
@Override
public void readFields(DataInput in) throws IOException{
//返回writable例項的反序列化流,注意:欄位的順序和write()方法相同
min=in.readInt();
max=in.readInt();
count=in.readLong();
average=in.readDouble();
}
@Override
public void write(DataOutput out) throws IOException{
//返回writable例項的反序列化流,注意:欄位的順序和write()方法相同
out.writeInt(this.min);
out.writeInt(this.max);
out.writeLong(this.count);
out.writeDouble(this.average);
}
//定義toString在輸出時才能正確解析
public String toString(){
return "min:"+min+" "+"max:"+max+" "+"count:"+count+" "+"average:"+average;
}
}
2)mapper程式碼
輸出鍵是使用者ID,輸出值是最大評分、最小評分及使用者評分數。這三個欄位存貯在MinMaxCountTuple型別的Writable物件中。在map端,我們將最大評分、最小評分都設定成了當前讀入資料中的評分值。計數值為1,表示該使用者評分了一次,最後所有的計數將在reduce端進行彙總。
public static class MinMaxCountMapper extends Mapper<Object, Text, Text, MinMaxCountTuple>{
private Text outUserId=new Text();//輸出健
private MinMaxCountTuple outTuple=new MinMaxCountTuple();//輸出值,為自定義型別
public void map(Object key, Text value, Context context) throws IOException,InterruptedException{
String[] data=value.toString().split(" ");
if(data.length==4){
//輸出的鍵
outUserId=new Text(data[0]);
//輸出的值,自定義Writable型別
outTuple.setMin(Integer.valueOf(data[2]));//最小評分
outTuple.setMax(Integer.valueOf(data[2]));//最大評分
outTuple.setAverage(Double.valueOf(data[2]));//平均評分
outTuple.setCount(1);//評分數目計數
}
context.write(outUserId, outTuple);
}
}
3)reducer程式碼
reducer遍歷(一個鍵對應的)所有值得到其最小評分、最大評分並計算次數的總和。
public static class MinMaxCountReducer extends Reducer<Text, MinMaxCountTuple, Text,MinMaxCountTuple>{
private MinMaxCountTuple result=new MinMaxCountTuple();
public void reduce(Text key, Iterable<MinMaxCountTuple> values, Context context) throws IOException,InterruptedException{
//初始化
result.setMin(100);
result.setMax(0);
result.setAverage(0.0);
result.setCount(0);
double average=0;
double sumNew=0;
int countNew=0;
//迭代迴圈這個鍵值的所有輸入
for(MinMaxCountTuple val:values){
if(result.getMax()<val.getMax()){
result.setMax(val.getMax());
}
if(result.getMin()>val.getMin()){
result.setMin(val.getMin());
}
//注意sumNew+=平均評分*評分次數
sumNew+=val.getAverage()*val.getCount();//評分和
countNew+=val.getCount();//評分次數
}
result.setCount(countNew);
average=sumNew/countNew;
result.setAverage(average);
context.write(key, result);
}
}
4)combiner優化
本示例為了直接使用reducer作為combiner進行了特殊處理,本來計算最大評分,最小評分,和統計使用者評分數是滿足交換律和結合律的,意思就是可以任意的改變值的順序,並且隨意的將計算進行分組但是不會該別最終的計算結果,那麼就可以使用combiner。
但是計算平均值是不滿足交換率和結合律的,因為如果每個combiner對本地的map輸出計算平均值,再將各自計算的到的平均值傳送到reduce進行平均值計算,得到的結果會是錯誤的。即,平均值的平均值與真實值的平均值不同。
因此,為了避免以上錯誤,同時利用combiner來優化計算,在計算總評分的時候使得:
評分總和+=平均評分*評分次數
這樣就可滿足交換律和結合律,可以使用combiner對本地map的輸出進行計算。
總結
combiner的使用:只有在map輸出資料的處理滿足交換律和結合律的情況下才能使用combiner。
相關文章
- 求陣列之和,最小值,最大值,平均值陣列
- 同時找到最大值和最小值——程式設計之美程式設計
- python 計算中位數、四分位數、最大值、最小值等Python
- 數值計算基礎
- Shell 指令碼迴圈遍歷日誌檔案中的值進行求和並計算平均值,最大值和最小值指令碼
- JavaScript可以設定最大值和最小值的隨機數JavaScript隨機
- JavaScript陣列最大值、最小值和平均數JavaScript陣列
- Linux中awk命令正確的求最大值、最小值、平均值、總和Linux
- 簡單的計算最值的MapReduce程式
- shell程式設計基礎二程式設計
- mapreduce的程式設計模型,計數器程式設計模型
- 《計算機基礎與程式設計》第二週學習總結計算機程式設計
- Shell程式設計-04-Shell中變數數值計算程式設計變數
- JavaScript 陣列最大值和最小值JavaScript陣列
- JavaScript 陣列 最大值和最小值JavaScript陣列
- JavaScript陣列最大值和最小值JavaScript陣列
- float型別最大值和最小值型別
- 2419 求最大值和最小值
- 程式設計必備基礎 計算機組成原理+作業系統+計算機網路,計算機基礎——更適合程式設計師的程式設計必備基礎知識作業系統計算機網路程式設計師
- 併發程式設計——基礎概念(二)程式設計
- 最大值減不為0的最小值
- 最大值(最短路+最短路計數)
- 數值計算的可靠性(二)
- js獲取數字陣列中的最大值和最小值程式碼例項JS陣列
- Python實用技法第7篇:字典上對資料執行計算:求最小值、最大值、排序Python排序
- 學習計算機程式設計需要什麼基礎?計算機程式設計
- JAVA 求出一個一維int型陣列的元素最大值、最小值、平均值、和所有元素之和Java陣列
- 程式設計基礎程式設計
- JavaScript獲取陣列最大值和最小值JavaScript陣列
- JavaScript陣列中的最大值和最小值JavaScript陣列
- int float double 各型別的最大值最小值型別
- 1.2程式設計基礎之變數定義、賦值及轉換程式設計變數賦值
- 數字之魅:尋找陣列中的最大值和最小值陣列
- Go語言實現時間滑動視窗演算法 動態計算增加量、最大值、最小值Go演算法
- C++程式設計基礎(2)變數C++程式設計變數
- fd最大值和限制 linux 下 file-max 的最大值計算方法Linux
- 計算機基礎第二課時計算機
- MapReduce--程式設計模板程式設計