1,读取文件
from pyspark import SparkContext
sc = SparkContext('local', 'pyspark')
a,text = sc.textFile(“file:///d:/test.txt”)
b,rdd = sc.parallelize([1,2,3,4,5])
2,RDD的操作
大家还对python的list comprehension有印象吗,RDDs可以进行一系列的变换得到新的RDD,有点类似那个过程,我们先给大家提一下RDD上最最常用到的transformation:
numbersRDD = sc.parallelize(range(1,10+1))
print(numbersRDD.collect())
squaresRDD = numbersRDD.map(lambda x: x**2) # Square every number
print(squaresRDD.collect())
filteredRDD = numbersRDD.filter(lambda x: x % 2 == 0) # Only the evens
结果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[2, 4, 6, 8, 10]
flatMap()与Map()的关系相当于,Python中list的extend和append的关系。
前面提到的Transformation,可以一个接一个地串联,比如:
def doubleIfOdd(x):
if x % 2 == 1:
return 2 * x
else:
return x
resultRDD = (numbersRDD # In parentheses so we can write each
.map(doubleIfOdd) # transformation in one line
.filter(lambda x: x > 6)
.distinct())
resultRDD.collect()
结果:
[8, 10, 18, 14]
3,RDD间的操作
如果你手头上有2个RDD了,下面的这些操作能够帮你对他们以个种方式组合得到1个RDD:
numbersRDD = sc.parallelize([1,2,3])
moreNumbersRDD = sc.parallelize([2,3,4])
numbersRDD.union(moreNumbersRDD).collect()
结果:
[1, 2, 3, 2, 3, 4]
特别注意:Spark的一个核心概念是惰性计算。当你把一个RDD转换成另一个的时候,这个转换不会立即生效执行!!!
Spark会把它先记在心里,等到真的需要拿到转换结果的时候,才会重新组织你的transformations(因为可能有一连串的变换)
这样可以避免不必要的中间结果存储和通信。
刚才提到了惰性计算,那么什么东西能让它真的执行转换与运算呢? 是的,就是我们马上提到的Actions,下面是常见的action,当他们出现的时候,表明我们需要执行刚才定义的transform了:
rdd = sc.parallelize(range(1,10+1))
rdd.reduce(lambda x, y: x + y)
结果:
55
5,针对更复杂结构的transform和action
有时候我们会遇到更复杂的结构,比如非常非常经典的是以元组形式组织的k-v对(key, value)我们把它叫做pair RDDs,而Sark中针对这种item结构的数据,定义了一些transform和action:
rdd = sc.parallelize(["Hello hello", "Hello New York", "York says hello"])
resultRDD = (
rdd
.flatMap(lambda sentence: sentence.split(" ")) # split into words
.map(lambda word: word.lower()) # lowercase
.map(lambda word: (word, 1)) # count each appearance
.reduceByKey(lambda x, y: x + y) # add counts for each word
)
resultRDD.collect()
结果:
[('says', 1), ('new', 1), ('hello', 4), ('york', 2)]
若将结果以k-v字典的形式返回:
result = resultRDD.collectAsMap()
结果:
{'hello': 4, 'new': 1, 'says': 1, 'york': 2}
如果你想要出现频次最高的2个词,可以这么做:
print(resultRDD
.sortBy(keyfunc=lambda (word, count): count, ascending=False)
.take(2))
结果:
[('hello', 4), ('york', 2)]
6,在给定2个RDD后,我们可以通过一个类似SQL的方式去join他们
如:
homesRDD = sc.parallelize([
('Brussels', 'John'),
('Brussels', 'Jack'),
('Leuven', 'Jane'),
('Antwerp', 'Jill'),
])
# Quality of life index for various cities
lifeQualityRDD = sc.parallelize([
('Brussels', 10),
('Antwerp', 7),
('RestOfFlanders', 5),
])
homesRDD.join(lifeQualityRDD).collect()
结果为:
[('Antwerp', ('Jill', 7)),
('Brussels', ('John', 10)),
('Brussels', ('Jack', 10))]
homesRDD.leftOuterJoin(lifeQualityRDD).collect()
结果为:
[('Antwerp', ('Jill', 7)),
('Brussels', ('John', 10)),
('Brussels', ('Jack', 10)),
('Leuven', ('Jane', None))]