標籤:函數 min count 代碼 笛卡爾 lines 例子 參數表 資料類型
---------------------
本節內容:
· Spark轉換 RDD操作執行個體
· Spark行動 RDD操作執行個體
· 參考資料
---------------------
關於學習編程方式的,每個人都有自己的方式。對我個人來說,最好的方法還是多動手寫demo,要多寫代碼,才能理解的更加深刻,本節以例子的形式講解各個Spark RDD的使用方法和注意事項,本文一共講解了20個RDD的使用demo。
一、Spark轉換 RDD操作執行個體
RDD轉換操作返回的是RDD,而行動操作返回的是其他資料類型。
1.例子:textFile/collect/foreach
---------------------
val line =sc.textFile("/tmp/test/core-site.xml");
line.collect().foreach(println);
------
說明:
textFile:讀取hdfs資料
collect:收集RDD資料集
foreach:迴圈遍曆列印出來
---------------------
val line =sc.parallelize(List(1,2,3,4));
line.map(x=>x*x);
line.collect().mkString(",").foreach(print);
------
說明:
parallelize:從外部資料集建立RDD
map:接收一個函數,把這個函數作用於RDD中的每一個元素,輸入類型和傳回型別不需要相同。
mkString:增加分隔字元
---------------------
2.例子:flatMap/first
---------------------
val lines =sc.parallelize(List("hello world","hi hi hhe"));
val words=lines.flatMap(line => line.split(" "));
words.collect().foreach(println);
words.first();
------
說明:
flatMap:flatMap將返回的迭代器拍扁,將迭代器中的多個RDD中的元素取出來組成一個RDD.
first:收集RDD資料集中的第一個資料
---------------------
3.例子:filter/union
---------------------
val lines =sc.textFile("/tmp/test/core-site.xml");
val name=lines.filter(line =>line.contains("name"));
val value=lines.filter(line =>line.contains("value"));
val result=name.union(value);
result.collect().foreach(println);
------
說明:
filter:不會改變RDD中的內容,將滿足filter條件的元素返回,形成新的RDD.
union:將兩個RDD的內容合并成一個RDD,操作的是兩個RDD.需要兩個RDD中的元素類型是相同的.
---------------------
4.例子:distinct/sample/intersection/subtract/cartesian
---------------------
val lines =sc.parallelize(List(1,2,3,4,1,2,3,3));
val result = lines.distinct();
result.collect().foreach(println);
val a = sc.parallelize(1 .to(1000),3);
val result = a.sample(false,0.02,0);
result.collect().foreach(println);
val a=sc.parallelize(List(1,2,3,4));
val b=sc.parallelize(List(1,2));
val result=a.intersection(b);
val result2=a.subtract(b);
result.collect().foreach(println);
result2.collect().foreach(println);
val a=sc.parallelize(List("a","b","c"));
val b=sc.parallelize(List("1","2"));
val result=a.cartesian(b);
result.collect().foreach(println);
------
說明:
distinct:對RDD中元素去重,會觸達shuffle操作,低效
sample:對RDD中的集合內元素進行採樣,第一個參數withReplacement是true表示有放回取樣,false表示無放回。第二個參數表示比例(取出元素個數佔比),第三個參數是隨機種子。
intersection:求兩個RDD共同的元素的RDD,回去重,引發shuffle操作.
subtract:移除RDD中的內容,會引發shuffle操作.
cartesian:求笛卡爾積,大規模資料時開銷巨大.
---------------------
二、Spark行動 RDD操作執行個體
1.例子:reduce/fold/aggregate[action操作]
--------reduce-------------
val line =sc.parallelize(List(1,2,3,4));
val sum = line.reduce((x,y) =>x+y);
println(sum);
--------fold-------------
val line =sc.parallelize(List(1,2,3,4),2);
val sum = line.fold(1)((x,y) =>x+y);
println(sum);
--------aggregate demo01-------------
val line =sc.parallelize(List(1,2,3,4));
val result= line.aggregate((0,0))(
(acc,value)=>(acc._1+value,acc._2+1),
(acc1,acc2) =>(acc1._1+acc2._1,acc1._2+acc2._2)
);
val avg=result._1/result._2.toDouble;
println(avg);
--------aggregate demo02-------------
def seqOP(a:Int,b:Int):Int={
println("seqOp:"+a+"\t"+b)
math.min(a,b)
}
def comOp(a:Int,b:Int):Int={
println("comOp:"+a+"\t"+b)
a+b
}
val line=sc.parallelize(List(1,2,3,4,5),1);
val result=line.aggregate(2)(seqOP,comOp);
println(result);
------
說明:
reduce:接收一個函數作為參數,函數將兩個相同元素類型的RDD資料並返回同一個類型的新元素.
fold:將兩個RDD的內容合并成一個RDD,操作的是兩個RDD.需要兩個RDD中的元素類型是相同的.fold計算過程是這樣的,
假如line 只有1個partition
第一個partition計算
第一次:1+1=2;
第二次:2+2=4;
第三次:3+4=7;
第四次:4+7=11;
combie計算:
第一次:11+1=12,最終結果:12
假如line 有2個partion【val line =sc.parallelize(List(1,2,3,4),2);】
第一個partition計算
第一次:1+1=2;
第二次:2+2=4;
第二個partition計算
第三次:3+1=4;
第四次:4+4=8;
combie計算:
第一次:4+1=5;
第二次:5+8=13
最終結果:13
aggregate:執行過程
//demo1執行過程
step1:(0+1,0+1)=(1,1)
step2:(1+2,1+1)=(3,2)
step3:(3+3,2+1)=(6,3)
step4:(4+6,3+1)=(10,4)
step5:(0+10,0+4)=(10,4)
avg=10/4=2.5
//demo2執行過程
step1:math.min(2,1)=1
step2:math.min(1,2)=1
step3:math.min(1,3)=1
step4:math.min(1,4)=1
step4:math.min(1,5)=1
step5:2+1=3
2.count/countByValue/take/top/takeOrdered
---------------------
val line=sc.parallelize(List(1,2,3,3),1);
val result=line.count();
println(result);
val line=sc.parallelize(List(1,2,3,3),1);
val result=line.countByValue();
println(result);
val line=sc.parallelize(List(1,2,3,3),1);
val result=line.take(3);
result.foreach(println);
val line=sc.parallelize(List(1,2,3,3),1);
val result=line.top(2);
result.foreach(println);
val line=sc.parallelize(List(1,2,3,3),1);
val result=line.takeOrdered(2);
result.foreach(println);
val line=sc.parallelize(List(1,2,3,3),1);
val result=line.takeSample(false,2);
result.foreach(println);
------
說明:
count:返回RDD中元素的個數.
countByValue: 各元素在RDD中出現的次數.
take:從RDD中取出前n個元素個數,與collect比,都是從遠程叢集上擷取元素,只是collect操作擷取的所有資料,而take操作是擷取前n個元素.
top:返回最前面的n個元素.
takeOrdered:從RDD中按照提供的順序返回最前面n個元素.
takeSample:從RDD中返回任意一些元素.
---------------------
三、參考資料
1.fold計算過程-http://www.aboutyun.com/home.php?mod=space&uid=1&do=blog&id=368
2.fold計算過程-http://www.cnblogs.com/MOBIN/p/5414490.html#12
3.aggregate計算過程-https://www.iteblog.com/archives/1268.html
【spark 深入學習 05】RDD編程之旅基礎篇02-Spaek shell