引入Python中pyspark工作模块
import pyspark
from pyspark import SparkContext as sc
from pyspark import SparkConf
conf=SparkConf().setAppName("miniProject").setMaster("local[*]")
sc=SparkContext.getOrCreate(conf)
#任何Spark程序都是SparkContext开始的,SparkContext的初始化需要一个SparkConf对象,SparkConf包含了Spark集群配置的各种参数(比如主节点的URL)。初始化后,就可以使用SparkContext对象所包含的各种方法来创建和操作RDD和共享变量。Spark shell会自动初始化一个SparkContext(在Scala和Python下可以,但不支持Java)。
# getOrCreate表明可以视情况新建session或利用已有的session
加载数据
初始化RDD的方法
(1)本地内存中已经有一份序列数据(比如python的list),可以通过sc.parallelize去初始化一个RDD。当执行这个操作以后,list中的元素将被自动分块(partitioned),并且把每一块送到集群上的不同机器上。
data = [1,2,3,3]
rdd1 = sc.parallelize(data)
print(rdd1.collect())
(2)创建RDD的另一个方法是直接把文本读到RDD。文本的每一行都会被当做一个item,不过需要注意的一点是,Spark一般默认给定的路径是指向HDFS的,如果要从本地读取文件的话,给一个file://开头(windows下是以file:\开头)的全局路径
data = sc.textFile('C:\\Users\\theone\\Desktop\\page_views.dat')
RDD Transformation
(1)RDDs可以进行一系列的变换得到新的RDD,有点类似列表推导式的操作,先给出一些RDD上最常用到的transformation:
map() 对RDD的每一个item都执行同一个操作
rdd1 = data.map(lambda x:x.split("\t"))
flatMap() 对RDD中的item执行同一个操作以后得到一个list,然后以平铺的方式把这些list里所有的结果组成新的list
rdd1 = data.flatmap(lambda x:x.split("\t"))
filter() 筛选出来满足条件的item
rdd1 = sc.parallelize(data).filter(lambda x:(x>3))
distinct() 对RDD中的item去重
rdd1 = data.map(lambda x: x.split("\t")[1]).distinct()
sample() 从RDD中的item中采样一部分出来,有放回或者无放回
sortBy() 对RDD中的item进行排序,默认升序
.sortByKey(False)
完整程序示例:
from pyspark import SparkConf,SparkContext
if __name__ == '__main__':
conf = SparkConf()
sc = SparkContext(conf=conf)
def printResult():
data = sc.textFile('C:\\Users\\75473\\Desktop\\page_views.dat')
rdd1 = data.map(lambda x: x.split("\t")) \
.map(lambda x:(x[1],x[5]))\
.map(lambda x: (x[0].split("/"),x[1])).map(lambda x: (x[0][2],x[1])).distinct() \
.map(lambda x:(x,1)).map(lambda x:(x[0][0],x[1]))\
.reduceByKey(lambda a,b:a+b).map(lambda x:(x[1],x[0]))\
.sortByKey(False).map(lambda x:(x[1],x[0]))
print(rdd1.collect())
(2)对(key, value),Spark定义了一些transform和action:
reduceByKey() # 对所有有着相同key的items执行reduce操作
groupByKey() # 返回类似(key, listOfValues)元组的RDD,后面的value List 是同一个key下面的
sortByKey() # 按照key排序
countByKey() # 按照key去对item个数进行统计
collectAsMap() # 和collect有些类似,但是返回的是k-v的字典
(1)如果有2个RDD,可以通过下面这些操作,对它们进行集合运算得到1个新的RDD
rdd1.union(rdd2) # 以rdd1为准求并集)
rdd1.intersection(rdd2) # 求交集
rdd1.substract(rdd2) # 所有在rdd1中但不在rdd2中的item(差集)
rdd1.cartesian(rdd2) # rdd1 和 rdd2中所有的元素笛卡尔乘积(正交和)
惰性计算,actions方法
特别注意:Spark的一个核心概念是惰性计算。当你把一个RDD转换成另一个的时候,转换不会立即生效执行!!!等到有actions时,才会重新组织transformations(因为可能有一连串的变换)。这样可以避免不必要的中间结果存储和通信。
常见的action如下,当它们出现的时候,表明需要执行上面定义过的transform了:
collect() # 计算所有的items并返回所有的结果到driver端,接着 collect()会以Python list的形式返回结果
first() # 和上面是类似的,不过只返回第1个item
take(n) # 类似,但是返回n个item
count() # 计算RDD中item的个数
top(n) # 返回头n个items,按照自然结果排序
reduce() # 对RDD中的items做聚合