文章目录
一、连接pyspark
先启动hadoop和spark
cd $HADOOP_HONE
sbin/start-all.sh
cd $SPARK_HONE
sbin/start-all.sh
jps
'''
30066 DataNode
31795 Jps
29972 NameNode
30404 NodeManager
30197 SecondaryNameNode
30520 Master
30634 SparkSubmit
30317 ResourceManager
30558 Worker
30590 Worker
'''
创建SparkContext
任何Spark程序都是SparkContext开始的,SparkContext的初始化需要一个SparkConf对象,SparkConf包含了Spark集群配置的各种参数(比如主节点的URL)。初始化后,就可以使用SparkContext对象所包含的各种方法来创建和操作RDD和共享变量。Spark shell会自动初始化一个SparkContext(在Scala和Python下可以,但不支持Java)。
方式1:通过pyspark下的shell.py
import os
import sys
spark_name = os.environ.get('SPARK_HOME',None)
if not spark_name:
raise ValueErrorError('spark环境没有配置好')
sys.path.insert(0,os.path.join(spark_name,'python'))
sys.path.insert(0,os.path.join(spark_name,'python/lib/py4j-0.10.7-src.zip'))
exec(open(os.path.join(spark_name,'python/pyspark/shell.py')).read())
出现下图说明已经连接好了。
方式2:自行创建
通过下面的方式,同样可以创建一个sc。
from pyspark import SparkConf, SparkContext
conf = SparkConf().setMaster("local").setAppName("My App")
sc = SparkContext.getOrCreate(conf)
#getOrCreate表明可以视情况新建session或利用已有的session
二、创建RDD
使用以下两种方式创建RDD。
并行集合 sc.parallelize()
来自分布式化的数据对象,比如Python中的list对象,或者自己键入的数据。
并行化RDD通过调用sc的parallelize方法,在一个已经存在的数据集合上创建(一个Seq对象)。集合的对象会被拷贝,创建出一个可以被并行操作的分布式数据集。
list_data = list(range(1,7))
vec = sc.parallelize(list_data)
type(vec) #pyspark.rdd.RDD
vec.collect() #[1, 2, 3, 4, 5, 6]
vec.count() #6
文件系统数据集读取数据 sc.textFile()
Spark可以将任何hadoop所支持的存储资源转换为RDD,如本地文件(语言网络文件系统)、HDFS、Mongodb、HBase等。
# 以下为我的本地环境中存在的数据文件
lines = sc.textFile("hdfs://localhost:9000/custom_data/shopping/customer/customer_details.csv")
lines.count()
type(lines)
lines.collect()[:5]
三、单个RDD的操作
map()和flatMap()
map()是将文件每一行进行操作,数量不会改变;flatMap()是将所有元素进行操作,数量会大于或者等于初始数量。
- map()
rdd = lines.map(lambda x: x.split(','))
rdd.collect()[:2]
'''
[['customer_id',
'first_name',
'last_name',
'email',
'gender',
'address',
'country',
'language',
'job',
'credit_type',
'credit_no'],
['1',
'Spencer',
'Raffeorty',
'sraffeorty0@dropbox.com',
'Male',
'9274 Lyons Court',
'China',
'Khmer',
'Safety Technician III',
'jcb',
'3589373385487669']]
'''
- flatMap()
rdd_flat = lines.flatMap(lambda x: x.split(','))
rdd_flat.collect()[:20]
'''
['customer_id',
'first_name',
'last_name',
'email',
'gender',
'address',
'country',
'language',
'job',
'credit_type',
'credit_no',
'1',
'Spencer',
'Raffeorty',
'sraffeorty0@dropbox.com',
'Male',
'9274 Lyons Court',
'China',
'Khmer',
'Safety Technician III']
'''
过滤 filter()
将符合条件的数据保留下来。
rdd_filter = rdd_flat.filter(lambda x: len(x)>10)
rdd_filter.collect()[:20]
'''
['customer_id',
'credit_type',
'sraffeorty0@dropbox.com',
'9274 Lyons Court',
'Safety Technician III',
'3589373385487669',
'cpoynor1@51.la',
'1377 Anzinger Avenue',
'Research Nurse',
'instapayment',
'6376594861844533',
'nabendroth2@scribd.com',
'2913 Evergreen Lane',
'Budget/Accounting Analyst IV',
'4041591905616356',
'hseally3@prlog.org',
'694 Del Sol Lane',
'Environmental Specialist',
'677118310740263477',
'dcoad4@weibo.com']
'''
reduce()和reduceByKey()
- reduce()
reduce()将RDD中元素的前两个传给输入函数,产生一个新的return值。新产生的return值与RDD中的下一个元素(第三个元素)组成两个元素,再被传给输入函数,直到最后只有一个值为止。
list_data = list(range(1,7))
vec = sc.parallelize(list_data)
total = vec.reduce(lambda x,y: x+y)
total # 21
- reduceByKey()
reduceByKey()是对元素为键值对的RDD中,key相同的元素值进行reduce操作。key相同的多个元素会被reduce为一个值,然后与原RDD的key组成一个新的键值对。
# 统计文章中相同的单词数 wordcount
rdd = lines.flatMap(lambda x: x.split(',')).map(lambda x: (x,1))
rdd_reduce = rdd.reduceByKey(lambda x,y: x+y)
rdd_reduce.collect()[:5]
countByValue()
rdd.countByValue()
四、两个RDD之间的集合操作
rdd1.union(rdd2): 所有rdd1和rdd2中的item组合(并集)
rdd1.intersection(rdd2): rdd1 和 rdd2的交集
rdd1.substract(rdd2): 所有在rdd1中但不在rdd2中的item(差集)
rdd1.cartesian(rdd2): rdd1 和 rdd2中所有的元素笛卡尔乘积(正交和)