spark2.x由淺入深深到底系列七之RDD python api詳解二

學習spark任何技術之前請先正確理解spark,可以參考:正確理解Spark


本文詳細介紹RDD python api的action操作。


先創建一個RDD:

conf = SparkConf().setAppName("appName").setMaster("local")
sc = SparkContext(conf=conf)

parallelize_rdd = sc.parallelize([1, 2, 4, 3, 3, 6, 12], 2)


一、collect、take

"""
結果:[[1, 2, 4], [3, 3, 6]]。收集RDD的所有元素
"""
print "parallelize_rdd = {0}".format(parallelize_rdd.glom().collect())
"""
結果:[1, 2]  獲取RDD的第一個分區的前兩個元素
"""
print "take(2) = {0}".format(parallelize_rdd.take(2))


二、top

"""
結果:[12, 6] 獲取RDD的最大的兩個元素
"""
print "top2 = {0}".format(parallelize_rdd.top(2))
"""
結果:[6, 4] 將RDD的元素轉化成字符串,然後按照字符串的比較規則取最大的兩個元素
"""
print "top(2, key=str) = {0}".format(parallelize_rdd.top(2, key=str))

接下來,詳細講解top的第二個參數:

"""
top的第二個參數是一個函數,一般是lambda表達式,可以看下面python內置的max的例子
當設置了這個key參數的時候,表示將數組中的元素應用這個key函數,按照返回的值來進行排序或者取最大值
"""
d1 = {'name': 'egon', 'price': 100}
d2 = {'name': 'rdw', 'price': 666}
d3 = {'name': 'zat', 'price': 1}
l1 = [d1, d2, d3]
"""
表示取數組 l1 中name最大的那個元素的值
"""
a = max(l1, key=lambda x: x['name'])
"""
結果是:{'price': 1, 'name': 'zat'}
"""
print(a)
"""
表示取數組 l1 中price最大的那個元素的值
"""
b = max(l1, key=lambda x: x['price'])
"""
結果是:{'price': 666, 'name': 'rdw'}
"""
print(b)


三、first、min、max、takeOrdered

"""
結果:first = 1
"""
print "first = {0}".format(parallelize_rdd.first())

"""
結果:min = 1. 這個參數和上面top的第二個參數是一個含義
"""
print "min = {0}".format(parallelize_rdd.min(key=lambda x: str(x)))

"""
結果:max = 12
"""
print "max = {0}".format(parallelize_rdd.max())

"""
結果:takeOrdered = [1, 12]  第二個參數和上面top的第二個參數是同一個含義
"""
print "takeOrdered = {0}".format(parallelize_rdd.takeOrdered(2, key=str))


四、foreach、foreachPartition

def get_init_number(source):
    print "get init number from {0}, may be take much time........".format(source)
    time.sleep(1)
    return 1

def foreach_fun(x):
    init_number = get_init_number("foreach")
    print x + init_number + "==========="
parallelize_rdd.foreach(foreach_fun)

def foreach_partition_fun(values):
    """
    和foreach api的功能是一樣,只不過一個是將函數應用到每一條記錄,這個是將函數應用到每一個partition
    如果有一個比較耗時的操作,只需要每一分區執行一次這個操作就行,則用這個函數
    這個耗時的操作可以是連接數據庫等操作,不需要計算每一條時候去連接數據庫,一個分區只需連接一次就行
    :param values:
    :return:
    """
    init_number = get_init_number("foreach")
    for item in values:
        print item + init_number + "==========="
parallelize_rdd.foreachPartition(foreach_partition_fun)


五、reduce、treeReduce

reduce_result = parallelize_rdd.reduce(lambda a, b: a + b)
print "reduce_result = {0}".format(reduce_result) # reduce_result = 31

tree_reduce_result = parallelize_rdd.treeReduce(lambda a, b: a + b, 2)
print "tree_reduce_result = {0}".format(tree_reduce_result) # tree_reduce_result = 31


六、fold

# 和reduce的功能類似,只不過是在計算每一個分區的時候需要加上初始值1,最後再將每一個分區計算出來的值相加再加上這個初始值
fold_result = parallelize_rdd.fold(0, lambda a, b: a + b)
print "fold_result = {0}".format(fold_result) # fold_result = 31


七、aggregate、treeAggregate

seqOp = (lambda x, y: (x[0] + y, x[1] + 1))
combOp = (lambda x, y: (x[0] + y[0], x[1] + y[1]))
aggregate_result = parallelize_rdd.aggregate((0, 0), seqOp, combOp)
print "aggregate_result = {0}".format(aggregate_result) #  aggregate_result = (31, 7)


對於reduce、treeReduce、fold、aggregate、treeAggregate的原理可以參考http://7639240.blog.51cto.com/7629240/1966172 和 spark core RDD api原理詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章