學習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原理詳解