Spark初步練習

Spark下載頁面:Spark官網

我是在雲服務器centOS7上安裝的,下載後解壓即可。

1,修改環境變量如下,一個HOME一個bin

vim /etc/profile
export SPARK_HOME=/usr/spark-2.4.0-bin-hadoop2.6
export PATH=$SPARK_HOME/bin:$PATH

 2,啓動,輸入spark-shell即可。

3,下載數據集。鏈接:donation數據集

4,解壓數據集,將其中block_*.csv的文件全部copy至一個文件夾,此處文件夾見下。

5,在shell窗口練習,具體如下:

//加載文件夾
 val rawblocks=sc.textFile("/usr/spark/linkage")
//定義函數,用於檢測每個csv文件的標題,數據集中不需要標題的。
def isHeader(s:String):Boolean={s.contains("id_1")}
//過濾掉帶標題的行
 val noheader=rawblocks.filter(x=> !isHeader(x))
//定義函數,將缺少的數據以NaN填充
def toDouble(s:String)={if("?".equals(s)) Double.NaN;else s.toDouble}
//創建case class,它是不可變類的一種簡單類型,類似js中一個對象,調用屬性比較方便
case class MatchData(id1:Int,id2:Int,scores:Array[Double],matched:Boolean)
//定義函數,用於解析每一行的數據,返回上面定義的封裝型對象
def parse(line:String)={
val pieces=line.split(",");
val id1=pieces(0).toInt;
val id2=pieces(1).toInt;
val scores=pieces.slice(2,11).map(toDouble);
val matched=pieces(11).toBoolean;
MatchData(id1,id2,scores,matched)
}
//對每一行進行parse處理
val parsed=noheader.map(line=>parse(line))

//創建StatsWithMissing.scala文件
import org.apache.spark.util.StatCounter;
class NAStatCounter extends Serializable{
	val stats:StatCounter=new StatCounter();
	var missing:Long=0;
def add(x:Double):NAStatCounter={
	if(java.lang.Double.isNaN(x)){
		missing +=1;
}
	else{stats.merge(x);}
this
}

def merge(other:NAStatCounter):NAStatCounter={
	stats.merge(other.stats);
	missing +=other.missing;
	this

}
override def toString={
"stats: "+stats.toString+" NaN: "+missing

}

}
//伴生單例對象,類似static語義
object NAStatCounter extends Serializable{
def apply(x:Double)=new NAStatCounter().add(x)
}
//文件結束

//加載文件,提示伴生單例對象在shell使用的增量編譯模式下是不合法的,但是仍然可以操作
:load /usr/spark/scala_file/StatsWithMissing.scala
//將每行scores部分數據再轉換成NAStatCounter對象
val nasRDD=parsed.map(md=>{md.scores.map(d=>NAStatCounter(d))})

//測試
val nas1=Array(1.0,Double.NaN).map(d=>NAStatCounter(d))
val nas2=Array(Double.NaN,2.0).map(d=>NAStatCounter(d))
val merged=nas1.zip(nas2).map(p=>p._1.merge(p._2))
//val merged=nas1.zip(nas2).map{case(a,b)=> a.merge(b)}也可
val nas=List(nas1,nas2)
val merged=nas.reduce((n1,n2)=>{n1.zip(n2).map{case(a,b)=>a.merge(b)}})
//測試結束

//zip將2個相同長度的數組合併成一個數組,新數組的每個元素爲原來2個數組中的元素對
//統計
val reduced=nasRDD.reduce((n1,n2)=>{n1.zip(n2).map{case(a,b)=>a.merge(b)}})

//將以下代碼添加到之前scala文件中,mapPartitions對每個分區作用
import org.apache.spark.rdd.RDD
def statsWithMissing(rdd:RDD[Array[Double]]):Array[NAStatCounter]={
	val nastats=rdd.mapPartitions((iter:Iterator[Array[Double]])=>{
	        //第一個元素
		val nas:Array[NAStatCounter]=iter.next().map(d=>NAStatCounter(d));
		iter.foreach(arr=>{
			nas.zip(arr).foreach{case(a,b)=>a.add(b)}
		});
		Iterator(nas)
		
	});
	nastats.reduce((n1,n2)=>{
			n1.zip(n2).map{case(a,b)=>a.merge(b)}
		})
}
//添加結束

//重新加載scala文件
:load /usr/spark/scala_file/StatsWithMissing.scala
//調用新加的函數分析其中的scores
val statsm=statsWithMissing(parsed.filter(_.matched).map(_.scores))
val statsn=statsWithMissing(parsed.filter(!_.matched).map(_.scores))
//統計匹配與不匹配的總丟失情況及平均值差異
statsm.zip(statsn).map{case(m,n)=>(m.missing+n.missing,m.stats.mean-n.stats.mean)}.foreach(println)
//一個好特徵有兩個屬性:第一,對匹配記錄和不匹配記錄它的值往往差別很大(因此均值
//的差異也很大);第二,在數據中出現的頻率高,這樣我們才能指望它在任何一對記錄裏
//都有值。

//結果。第2個特徵丟失多且差異小,所以作用不大。第5個特徵差異很小,影響也不大。第6和第8個
//特徵較好,選擇下標爲2,5,6,7,8的數據進行建模
(1007,0.2854529057466858)
(5645434,0.09104268062279897)
(0,0.6838772482597568)√ 0.8
(5746668,0.8064147192926268)
(0,0.0324081852503344)
(795,0.7754423117834044)√1.3
(795,0.5109496938298715)√ 0.6
(795,0.7762059675300523)√1.3
(12843,0.9563812499852178)√1

//定義函數,將NaN轉換爲0
def naz(d:Double)=if(Double.NaN.equals(d)) 0.0;else d
//定義封裝對象
case class Scored(md:MatchData,score:Double)
//以下標2,5,6,7,8爲有作用特徵,將其中缺少的NaN修改爲0後彙總,返回每個結果的總分
val ct=parsed.map(md=>{val score=Array(2,5,6,7,8).map(i=>naz(md.scores(i))).sum;Scored(md,score)})
//顯示總分大於等於4分,按匹配與否分別輸出
 ct.filter(s=>s.score>=4.0).map(s=>s.md.matched).countByValue()
 //以下結果表明平均值大於等於0.8的結果中有超過97%的匹配率,說明這個簡單模型還不錯
 Map(true -> 20871, false -> 637)
 //調整權重因子爲以上0.8-1.3-0.6-1.3-1後,結果爲:
 //Map(true -> 20780, false -> 626),正確率提升微乎其微,需要通過訓練得到更好的權重因子




 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章