Spark初步练习

本文介绍了在云服务器CentOS7上安装Spark的过程,下载后解压,修改环境变量,输入spark - shell启动。还提及下载并解压donation数据集,将block_*.csv文件复制到指定文件夹,最后可在shell窗口进行练习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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),正确率提升微乎其微,需要通过训练得到更好的权重因子




 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值