mllib是spark的机器学习库
依赖:
mllib的底层实现采用数值计算库Breeze和基础线性代数库BLAS
rdd惰性计算:
是为了提高效率,如果每次转换操作都运行一遍很消耗内存。
所致转换操作只记录下来,等到动作操作再执行。
RDD操作(scala):
创建:
val data = Array(1,2,3,4,5,6,7,8,9)
val distData = sc.parallelize(data,3)
第一个参数是数据集;第二个参数是分区(数据集划分成分片的数量),
典型情况下每个cpu运行2~4个分区。
读取外部数据源:
val distFile1 = sc.textFile("hdfs://192.168.80.139:9000/test/data.txt", 3)
可以读取多个:
val distFile1 = sc.textFile("/test/1.txt, /test/2.txt")
转换操作:
map:
对RDD中的元素执行函数
val rdd1 = sc.parallelize(1 to 9)
val rdd2 = rdd1.map(x => x*2)
rdd2.collect //scala中可以不写括号
filter:
对RDD中的元素进行过滤
val rdd3 = rdd2.filter(x => x>10)
flatMap:
以行为单位操作数据,针对分层的数据(数据集)进行操作,类似map,扁平化map,压平
val rdd4 = sc.parallelize(Array("a b c","d e f","h i j"))
val rdd5 = rdd4.flatMap(_.split(" "))
结果:
scala> rdd5.collect res1: Array[String] = Array(a, b, c, d, e, f, h, i, j)
此例:每个输入元素对应多个输出元素
来个复杂的:
scala> val r1 = sc.parallelize(List(List("a b c","a b b"),List("e f g","a f g"),List("h i j","a a b")))
scala> val r2 = r1.flatMap(_.flatMap(_.split(" ")))
scala> r2.collect
res0: Array[String] = Array(a, b, c, a, b, b, e, f, g, a, f, g, h, i, j, a, a, b)
解释:双层嵌套,第一个_取到了List("a b c","a b b"),不能直接split,
还要再进行一次flatMap(_.split(" "))
mapPartitions、mapPartitionsWithIndex:
map的变种,针对分区,把分区的内容作为整体来处理
sample:
sample(withReplacement, fraction, seed)
采样、抽取样本
withReplacement:是否放回的抽样,fraction:比例,seed:随机种子(建议不填)
rdd4.sample(false, 0.1, 0)
union:
联合
val rdd8 = rdd1.union(rdd3)
intersection :
交集
val rdd9 = rdd8.intersection(rdd1)
distinct :
去重
val rdd10 = rdd8.union(rdd9).distinct
groupByKey :
根据key对value分组
val RDD1 = sc.parallelize(Array(("tom",1), ("tom",2), ("tom",3), ("jerry",1), ("jerry",2), ("jerry",3)))
val RDD2 = RDD1.groupByKey()
RDD2.collect
res3: Array[(String, Iterable[Int])] = Array((tom,CompactBuffer(1, 2, 3)), (jerry,CompactBuffer(1, 2, 3)))
然后就可以mapValues了:
val RDD3 = RDD2.mapValues(_.sum)
RDD3.collect
res4: Array[(String, Int)] = Array((tom,6), (jerry,6))
reduceByKey :
根据key,对value执行函数
val RDD4 = RDD1.reduceByKey(_+_).collect
RDD4: Array[(String, Int)] = Array((tom,6), (jerry,6))
sortByKey :
根据key进行排序,默认升序
randomSplit:
样本划分
val rdd2 = rdd1.randomSplit(Array(0.3, 0.7))
rdd1(0).collect
substract :
减法,减去交集
val rdd1 = sc.parallelize(1 to 9)
val rdd2 = sc.parallelize(1 to 3)
val rdd3 = rdd1.substract(rdd2)
zip :
压缩操作,压缩成字典
val rdd1 = sc.parallelize(1 to 4)
val rdd2 = sc.parallelize(Array("a","b","c","d"))
val rdd3 = rdd1.zip(rdd2)
cache方法:
将数据内容保存到节点内存
rdd1.cache()
动作操作:
collect():
以array形式输出,scala中可以不写括号
println(rdd1.collect)显示的不是数组,可以使用toBuffer显示数组
count()、first()、take(5)、countByKey()
reduce(func):
对RDD所有元素执行聚集(func)函数
val rdd1 = sc.parallelize(1 to 9)
val rdd2 = rdd1.reduce(_ + _) //等同于val rdd2 = rdd1.reduce((x,y) => x+y)
rdd2: Int = 45
foreach(func):
对RDD每个元素执行func函数
saveAsTextFile :
保存为文件
持久化:
rdd1.peisist()
共享变量:
broadcast 广播变量:
广播出去的是变量不是RDD
scala> val x = 10
x: Int = 10
scala> val x1 = sc.broadcast(x)
x1: org.apache.spark.broadcast.Broadcast[Int] = Broadcast(2)
accumulator 累加器:
accumulator有两个参数,
第一个是累加器的初值,第二个是在Spark UI上显示的名字(可选)。
主要意义是全局变量。
1、累计器全局(全集群)唯一,只增不减(Executor中的task去修改,即累加);
2、累加器是Executor共享
scala> val data = sc.parallelize(Array(1,2,3,4,5,6,6,7,8,8,9))
data: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[5] at parallelize at <console>:43
scala> val sum = sc.accumulator(0)
sum: org.apache.spark.Accumulator[Int] = 0
scala> val result = data.foreach(item =>sum += item)
result: Unit = ()
scala> println(sum)
59