02_pyspark_rdd常见算子

常见的算子

rdd.map(f: (T) -> U)

def map_operator():
    conf = SparkConf().setMaster('local[*]').setAppName('map_operator')
    sc = SparkContext(conf=conf)

    rdd = sc.parallelize([1, 2, 3, 4, 5], 5)
    map_rdd = rdd.map(lambda x: x ** 2)
    print(map_rdd.collect())  # [1, 4, 9, 16, 25]

rdd.flatMap(f: (T) -> U)

对rdd执行map操作,然后进行扁平化

def flatMap_operator():
    conf = SparkConf().setMaster('local[*]').setAppName('map_operator')
    sc = SparkContext(conf=conf)

    rdd = sc.parallelize(['spark hadoop python', 'flatMap java scala', 'c c++ mr'])
    # flatMap_rdd = rdd.map(lambda word: word.split(" "))
    flatMap_rdd = rdd.flatMap(lambda word : word.split(" "))
    print(flatMap_rdd.collect())  # ['spark', 'hadoop', 'python', 'flatMap', 'java', 'scala', 'c', 'c++', 'mr']

rdd.reduceByKey(func: (V, V) -> V)

针对KV型,自动按照key分组,然后根据你提供的聚合逻辑,完成组内数据的聚合

def reduceByKey_operator():
    conf = SparkConf().setMaster('local[*]').setAppName('map_operator')
    sc = SparkContext(conf=conf)

    rdd = sc.parallelize(['spark hadoop python', 'flatMap java scala', 'c c++ mr', 'c python java scala'])

    reduceByKey_rdd = rdd.flatMap(lambda lis: lis.split(" ")).map(lambda world: (world, 1)).reduceByKey(
        lambda a, b: a + b)
    print(
        reduceByKey_rdd.collect())  # [('hadoop', 1), ('python', 2), ('spark', 1), ('scala', 2), ('java', 2), ('c', 2), ('c++', 1), ('mr', 1), ('flatMap', 1)]

rdd.mapValues(func: (V) -> U)

针对KV类型的RDD,对其内部的KV的Value执行map操作

def mapValues_operator():
    conf = SparkConf().setMaster('local[*]').setAppName('map_operator')
    sc = SparkContext(conf=conf)

    rdd = sc.parallelize(['spark hadoop python', 'flatMap java scala', 'c c++ mr', 'c python java scala'])

    mapValues_rdd = rdd.flatMap(lambda lis: lis.split(" ")).map(lambda world: (world, 1)).reduceByKey(
        lambda a, b: a + b).mapValues(lambda x: x ** 2)

    print(mapValues_rdd.collect())  # [('hadoop', 1), ('python', 4), ('spark', 1), ('scala', 4), ('java', 4), ('c', 4), ('c++', 1), ('mr', 1), ('flatMap', 1)]

rdd.groupBy(func: (T) -> K)

将rdd的数据进行分组

def groupBy_operator():
    conf = SparkConf().setMaster('local[*]').setAppName('map_operator')
    sc = SparkContext(conf=conf)

    rdd = sc.parallelize([('a', 1), ('b', 1), ('a', 2), ('b', 2), ('b', 3), ('a', 3)])

    groupBy_rdd = rdd.groupBy(lambda x : x[0])
    print(groupBy_rdd.collect())  # [('a', <pyspark.resultiterable.ResultIterable object at 0x00000213BEF3C288>), ('b', <pyspark.resultiterable.ResultIterable object at 0x00000213BEF3C208>)]
    result = groupBy_rdd.map(lambda x : (x[0], list(x[1])))
    print(result.collect())  # [('a', [('a', 1), ('a', 2), ('a', 3)]), ('b', [('b', 1), ('b', 2), ('b', 3)])]

rdd.filter(func : (T) -> bool)

过滤想要的数据

def filter_operator():
    conf = SparkConf().setMaster('local[*]').setAppName('map_operator')
    sc = SparkContext(conf=conf)

    rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7, 8, 9])
    filter_rdd = rdd.filter(lambda x: x % 2 == 0)
    print(filter_rdd.collect())  # [2, 4, 6, 8]

rdd.distinct(参数1)

参数1:去重分区数,一般不传

def distinct_operator():
    conf = SparkConf().setMaster('local[*]').setAppName('map_operator')
    sc = SparkContext(conf=conf)

    rdd = sc.parallelize([1, 2, 3, 1, 2, 3])
    distinct_rdd = rdd.distinct()
    print(distinct_rdd.collect())  # [1, 2, 3]

rdd.union(other_rdd)

将两个rdd合并成一个rdd返回,只合并,并不去重, rdd的类型不同也是可以合并的

def union_operator():
    conf = SparkConf().setMaster('local[*]').setAppName('map_operator')
    sc = SparkContext(conf=conf)

    rdd = sc.parallelize([1, 2, 3, 4])
    rdd2 = sc.parallelize([(1, 2), (3, 4)])

    union_rdd = rdd.union(rdd2)
    print(union_rdd.collect())  # [1, 2, 3, 4, (1, 2), (3, 4)]

rdd.join(other_rdd)

join算子只能用于二元元组, 对于join算子来说,关联条件按照二元元组的key来进行关联

def join_operator():
    conf = SparkConf().setMaster('local[*]').setAppName('map_operator')
    sc = SparkContext(conf=conf)

    rdd1 = sc.parallelize([('a', 1), ('b', 2), ('c', 3)])
    rdd2 = sc.parallelize([('b', 2), ('c', 3), ('d', 4)])

    join_rdd = rdd1.join(rdd2)
    print(join_rdd.collect())  # [('b', (2, 2)), ('c', (3, 3))]
    leftOuterJoin_rdd = rdd1.leftOuterJoin(rdd2)
    print(leftOuterJoin_rdd.collect())  # [('b', (2, 2)), ('c', (3, 3)), ('a', (1, None))]
    rightOuterJoin_rdd = rdd1.rightOuterJoin(rdd2)
    print(rightOuterJoin_rdd.collect())  # [('b', (2, 2)), ('c', (3, 3)), ('d', (None, 4))]

rdd.intersection(other_rdd)

功能:求2个rdd的交集,返回一个新的rdd

def intersection_operator():
    sc = spark()
    rdd1 = sc.parallelize([('a', 1), ('b', 2)])
    rdd2 = sc.parallelize([('b', 2), ('c', 3)])

    intersection_rdd = rdd1.intersection(rdd2)
    print(intersection_rdd.collect())  # [('b', 2)]

rdd.glom()

将rdd的数据,加上嵌套,这个嵌套是按照分区来进行的

def glom_operator():
    sc = spark()
    rdd = sc.parallelize([1, 2, 3, 4, 5, 6], 2)
    glom_rdd = rdd.glom()
    # 解嵌套
    flatMap_rdd = glom_rdd.flatMap(lambda x : x)
    print(glom_rdd.collect())  # [[1, 2, 3], [4, 5, 6]]
    print(flatMap_rdd.collect())  # [1, 2, 3, 4, 5, 6]

rdd.groupByKey()

针对KV类型的数据,自动按照key进行分组
注意groupBy() 和 groupByKey()返回的结果是不一样的

def groupByKey_operator():
    sc = spark()
    rdd = sc.parallelize([('a', 1), ('b', 2), ('c', 3), ('a', 'a'), ('b', 'b'), ('c', 'c')])
    groupByKey_rdd = rdd.groupByKey().map(lambda x : (x[0], list(x[1])))
    groupBy_rdd = rdd.groupBy(lambda x : x[0]).map(lambda x : (x[0], list(x[1])))

    print(groupByKey_rdd.collect())  # [('a', [1, 'a']), ('b', [2, 'b']), ('c', [3, 'c'])]
    print(groupBy_rdd.collect())  # [('a', [('a', 1), ('a', 'a')]), ('b', [('b', 2), ('b', 'b')]), ('c', [('c', 3), ('c', 'c')])]

rdd.sortBy(func: (T) -> U, ascending=False, numPartitions=1)

参数3:分区数, 这里的排序只能保证分区内有序,如果是生产环境下,可能会导致局部有序,如果要全局有序分区数要设置为1

def sortBy_operator():
    sc = spark()
    rdd = sc.parallelize([-1, 3, 5, 2, 6, 9])
    sortBy_rdd = rdd.sortBy(lambda x: x, ascending=True, numPartitions=2)
    # 参数1:表示按照什么来进行排序
    # 参数2:True升序,False降序
    # 参数3:分区数, 这里的排序只能保证分区内有序,如果是生产环境下,可能会导致局部有序,如果要全局有序分区数要设置为1
    print(sortBy_rdd.collect())  # [-1, 2, 3, 5, 6, 9]

rdd.sortByKey(ascending = True, numPartition = None, keyfunc=<function RDD.<lambda>>)

针对KV类型,按照K进行排序
参数3:在排序前对key进行处理,语法是(K) -> U,一个参数传入,返回一个值,并不会改变结果集上的值,而是改变排序时的值

def sortByKey_operator():
    sc = spark()
    rdd = sc.parallelize([('1', 'a'), ('3', 'c'), ('002', 'b'), ('09', 'z')])
    sortByKey_rdd = rdd.sortByKey(True, 1, lambda x : int(x))
    print(sortByKey_rdd.collect())  # [('1', 'a'), ('002', 'b'), ('3', 'c'), ('09', 'z')]

def spark()

def spark():
    conf = SparkConf().setMaster('local[*]').setAppName('rdd_test')
    # conf.set("spark.submit.pyFiles", "**.py")
    sc = SparkContext(conf=conf)
    return sc

rdd.countByKey()

行动算子, 统计key出现的次数

def countByKey_operator():
    sc = spark()
    rdd = sc.textFile("./data/words.txt")
    map_rdd = rdd.flatMap(lambda world: world.split(" ")).map(lambda world : (world , 1))
    countByKey_rdd = map_rdd.countByKey()
    print(type(countByKey_rdd))  # <class 'collections.defaultdict'>
    print(countByKey_rdd)  # defaultdict(<class 'int'>, {'hello': 3, 'spark': 1, 'hadoop': 1, 'flink': 1})

rdd.collect()

行动算子,将rdd各个分区中的数据,统一收集到Driver中,形成一个List()对象
这个算子,是将各个分区中的数据都拉取到Driver中,Rdd是一个分布式对象,其数据量非常的大,所以在使用这个算子之前要知道数据集的大小。

rdd.reduce(func :(T, T) -> U)

行动算子, 对RDD数据集按照你传入的逻辑进行聚合

def reudce_operator():
    from operator import add
    sc = spark()
    rdd = sc.parallelize([x+1 for x in range(10)])
    result = rdd.reduce(add)
    print(result)  # 55

rdd.flod()

和reduce一样,接受传入逻辑进行聚合,聚合是带有初始值的,这个初始值会作用在:分区内聚合和分区间聚合

def flod_operator():
    from operator import add
    sc = spark()
    rdd = sc.parallelize(range(10), 3)
    print(rdd.glom().collect())  # [[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]]
    flod_rdd = rdd.fold(10, add)
    """在分区内聚合:第一个分区:10 + 0 + 1 + 2 = 13
                  第二个分区:10 + 3 + 4 + 5 = 22
                  第三个分区:10 + 6 + 7 + 8 + 9 = 40
        分区间聚合: 10 + 13 + 22 + 40 = 85
    """
    print(flod_rdd)  # 85

rdd.first()

取出rdd的第一个元素

rdd.take(n)

取出rdd前n个算子,返回值是list

rdd.top(n)

对rdd的结果集,进行降序排序,取前n个

rdd.count()

计算rdd有多少条数据,返回值是一个数字

rdd.takeSample(参数1:True or False, 参数2:采样数,参数3:随机数种子)

随机抽样rdd的数据
参数1:True表示运行允许取同一个数据;False表示不允许取同一个数据,和数据内容无关,是否重复表示的是同一个位置的数据
参数2:抽取几个
参数3:随机数种子,这个参数传入一个数字即可,随机,一般不传,spark会自动分配

def takeSample_operator():
    sc = spark()
    rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 3, 1, 2])
    takeSample_rdd = rdd.takeSample(True, 20)  
    print(takeSample_rdd)  # [2, 2, 2, 6, 3, 3, 6, 1, 6, 1, 1, 1, 4, 5, 1, 4, 3, 3, 4, 3]
    takeSample_rdd2 = rdd.takeSample(False, 20)
    print(takeSample_rdd2)  # [4, 5, 2, 6, 2, 3, 1, 1, 3]

rdd.takeOrdered(参数1, 参数2)

对rdd进行排序取前N个数据
参数1:要几个数据
参数2:对排序的数据进行更改,但是不会影响数据本身,只是在排序的时候换个了样子

def takeOrdered_operator():
    sc = spark()
    rdd = sc.parallelize([-1, 3, 5, 2, 1, 0, -2])
    result = rdd.takeOrdered(4, lambda x: x ** 2)
    print(result)  # [0, -1, 1, 2]

rdd.foreach(func:(T) -> None)

对rdd的每一个元素,执行你提供的逻辑的操作(和map一个意思),但是这个方法没有返回值,每个分区会自己执行func函数,并不会把结果返回给Dirver端

def foreach_operator():
    sc = spark()
    rdd = sc.parallelize([1, 2, 3, 4, 5])

    rdd.foreach(lambda x : print(x, end = " ")) # 1 3 2 5 4

rdd.saveAsTextFile()

支持写入到本地文件系统,也支持写入到hdfs等文件系统,写出是每个分区执行,并不汇总到Driver端

rdd.mapPartitions(func:(iter) : list)

def mapPartition_operator():
    sc = spark()
    rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7], 3)

    def process(iter):
        resule = list()
        for i in iter:
            resule.append(i * 10)
        return resule
    mapPartitions_rdd = rdd.mapPartitions(lambda iter : process(iter))
    print(mapPartitions_rdd.collect())  # [10, 20, 30, 40, 50, 60, 70]

rdd.foreachPartition()

和普通的foreach一致,一次处理的是一整个分区数据,同时它也没有返回值

rdd.partitionBy(参数1, 参数2)

针对KV类型的rdd进行自定义分区操作
参数1:重新分区后有几个分区
参数2:自定义分区规则,函数传入

def partitionBy_operator():
    sc = spark()
    rdd = sc.parallelize([(1, 'a'), (2, 'b'), (3, 'c')], 2)
    # 默认分区
    print(rdd.glom().collect())  # [[(1, 'a')], [(2, 'b'), (3, 'c')]]
    # 自定义分区
    partitionBy_rdd = rdd.partitionBy(2, lambda x: x % 2 + 1)
    print(partitionBy_rdd.glom().collect())  # [[(1, 'a'), (3, 'c')], [(2, 'b')]]

rdd.repartition(N)

对rdd的分区执行重新分区(仅数量)
一般情况下,我们写spark代码除了要求全局排序设置1个分区外,多数的时候,所有API中关于分区相关的代码我们都不会理会,因为,如果修改了分区,①会影响到并行计算②分区如果增加,极大可能会导致shuffle

rdd.coalesce(分区数, shuffle = True, False)

如果要增加分区,需要将shuffle设置为True

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值