python实战spark(四)--RDD Resillient Distributed Dataset

RDD Resillient Distributed Dataset

Spark官方文档
class pyspark.RDD(jrdd, ctx, jrdd_deserializer=AutoBatchedSerializer(PickleSerializer()))
弹性分布式数据集(RDD),是Spark的基本抽象。表示可以并行操作的不可变的、分区的元素集合。
1.aggregate(zeroValue, seqOp, combOp)聚合每个分区的元素,然后使用给定的combine函数和一个中性的“零值”来聚合所有分区的结果。

函数op(t1, t2)允许修改t1并返回其结果值,以避免对象分配;但是不应该修改t2。

第一个函数(seqOp)可以返回与此RDD类型不同的结果类型U。因此,我们需要一个将T合并为U的操作和一个将两个U合并的操作。

>>> seqOp = (lambda x, y: (x[0] + y, x[1] + 1)) # 累加并计数,y为列表的元素,此处默认一个分区
>>> combOp = (lambda x, y: (x[0] + y[0], x[1] + y[1])) # 将每个分区的(sum,count)相加
>>> sc.parallelize([1, 2, 3, 4]).aggregate((0, 0), seqOp, combOp)
(10, 4)
>>> sc.parallelize([]).aggregate((0, 0), seqOp, combOp)
(0, 0)

2.aggregateByKey(zeroValue, seqFunc, combFunc, numPartitions=None, partitionFunc=<function portable_hash>)
使用给定的combine函数和一个中性的“零值”来聚合每个键的值。这个函数可以返回不同的结果类型U,而不是抽样值的类型,V .因此,我们需要为U V合并成一个操作,一个操作合并两个U(分区内),而后者用于合并分区之间的值。为了避免内存分配,这两个函数都允许修改和返回它们的第一个参数,而不是创建一个新的U。
3.barrier()
将当前阶段标记为barrier阶段,在此阶段Spark必须一起启动所有任务。如果任务失败,Spark将中止整个阶段并重新启动此阶段的所有任务,而不是只重新启动失败的任务。barrier执行模式是实验性的,它只处理有限的场景。
4.cache()
使用默认存储级别(MEMORY_ONLY)保存此RDD。
5.cartesian(other)
返回这个RDD和另一个RDD的笛卡尔积,即所有对元素(a, b)的RDD,其中a在self中,b在other中。

>>> rdd = sc.parallelize([1, 2])
>>> sorted(rdd.cartesian(rdd).collect())
[(1, 1), (1, 2), (2, 1), (2, 2)]

6.checkpoint()
将此RDD标记为检查点。它将被保存到SparkContext.setCheckpointDir()设置的目录中的一个文件中,所有对其父RDDs的引用都将被删除。必须在此RDD上执行任何job之前调用此函数。强烈建议将此RDD保存在内存中,否则将其保存到文件中将需要重新计算。
7.coalesce(numPartitions, shuffle=False)
返回一个新的指定分区数的RDD。

>>> sc.parallelize([1, 2, 3, 4, 5], 3).glom().collect()
[[1], [2, 3], [4, 5]]
>>> sc.parallelize([1, 2, 3, 4, 5], 3).coalesce(1).glom().collect()
[[1, 2, 3, 4, 5]]

8.cogroup(other, numPartitions=None)
对于self或other中的每个键k,返回一个结果RDD,该RDD包含一个元组,该元组包含self和other中该键的值列表。

>>> x = sc.parallelize([("a", 1), ("b", 4)])
>>> y = sc.parallelize([("a", 2)])
>>> [(x, tuple(map(list, y))) for x, y in sorted(list(x.cogroup(y).collect()))]
[('a', ([1], [2])), ('b', ([4], []))]

9.collect()
返回包含此RDD中的所有元素的列表。
10.collectAsMap()
将此RDD中的键值对作为字典返回。

>>> m = sc.parallelize([(1, 2), (3, 4)]).collectAsMap()
>>> m[1]
2
>>> m[3]
4

10.combineByKey(createCombiner, mergeValue, mergeCombiners, numPartitions=None, partitionFunc=<function portable_hash>)
使用一组自定义聚合函数组合每个键的元素。
将RDD[(K, V)] ==> RDD[(K, C)]。
提供三个函数:

  • createCombiner,将V转换为C(例如,创建一个单元素列表)
  • mergeValue将V合并成C(例如,将其添加到列表的末尾)
  • mergeCombiners将两个C合并成一个C(例如,合并列表)
    为了避免内存分配,mergeValue和mergecombiner都可以修改并返回它们的第一个参数,而不必创建一个新的C。
    此外,用户可以控制输出RDD的分区。
>>> x = sc.parallelize([("a", 1), ("b", 1), ("a", 2)])
>>> def to_list(a):
...     return [a]
...
>>> def append(a, b):
...     a.append(b)
...     return a
...
>>> def extend(a, b):
...     a.extend(b)
...     return a
...
>>> sorted(x.combineByKey(to_list, append, extend).collect())
[('a', [1, 2]), ('b', [1])]

11.property context
返回创建RDD的SaprkContext.
12.count()

>>> sc.parallelize([2, 3, 4]).count()
3

13.countApprox(timeout, confidence=0.95)
count()的近似版本,它在超时后返回一个可能不完整的结果,即使不是所有任务都已完成。
14.countApproxDistinct(relativeSD=0.05)
返回RDD中不同元素的近似数量。
所使用的算法是基于streamlib实现的“HyperLogLog in Practice: Algorithmic Engineering of a State of The Art Cardinality Estimation Algorithm”,这里可以找到。
参数:relativeSD–相对精度。较小的值创建需要更多空间的计数器。它必须大0.000017。
15.countByKey()
计算每个键的元素数,并将结果作为字典返回给主键。

>>> rdd = sc.parallelize([("a", 1), ("b", 1), ("a", 1)])
>>> sorted(rdd.countByKey().items())
[('a', 2), ('b', 1)]

16.countByValue()
将此RDD中每个唯一值的计数作为(值、计数)对的字典返回。

>>> sorted(sc.parallelize([1, 2, 1, 2, 2], 2).countByValue().items())
[(1, 2), (2, 3)]

17.distinct(numPartitions=None)
返回一个包含这个RDD中不同新的RDD.

>>> sorted(sc.parallelize([1, 1, 2, 3]).distinct().collect())
[1, 2, 3]

18.filter(f)
类似python的filter

>>> rdd = sc.parallelize([1, 2, 3, 4, 5])
>>> rdd.filter(lambda x: x % 2 == 0).collect()
[2, 4]

19.first()

>>> sc.parallelize([2, 3, 4]).first()
2
>>> sc.parallelize([]).first()
Traceback (most recent call last):
    ...
ValueError: RDD is empty

20.flatMap(f, preservesPartitioning=False)
返回一个新的RDD,首先将一个函数应用到这个RDD的所有元素上,然后将结果平铺。(是map的平铺版)

>>> rdd = sc.parallelize([2, 3, 4])
>>> sorted(rdd.flatMap(lambda x: range(1, x)).collect())
[1, 1, 1, 2, 2, 3]
>>> sorted(rdd.flatMap(lambda x: [(x, x), (x, x)]).collect())
[(2, 2), (2, 2), (3, 3), (3, 3), (4, 4), (4, 4)]

21.flatMapValues(f)
在不改变键值的情况下,通过平面映射函数传递键值对RDD中的每个值;这也保留了原始的RDD分区。

>>> x = sc.parallelize([("a", ["x", "y", "z"]), ("b", ["p", "r"])])
>>> def f(x): return x
>>> x.flatMapValues(f).collect()
[('a', 'x'), ('a', 'y'), ('a', 'z'), ('b', 'p'), ('b', 'r')]

22fold(zeroValue, op)
使用给定的关联函数和“零值”聚合每个分区的元素,然后聚合所有分区的结果。
允许函数op(t1, t2)修改t1并返回其结果值,以避免对象分配;但不应该修改t2。
这与Scala等函数式语言中为非分布式集合实现的折叠操作有些不同。此折叠操作可以应用于单独的分区,然后将这些结果折叠成最终结果,而不是按某些已定义的顺序将折叠应用于每个元素。对于不可交换的函数,其结果可能与应用于非分布式集合的折叠结果不同。

>>> from operator import add
>>> sc.parallelize([1, 2, 3, 4, 5]).fold(0, add)
15

23.foldByKey(zeroValue, func, numPartitions=None, partitionFunc=<function portable_hash>)
使用一个关联函数“func”和一个中立的“zeroValue”来合并每个键的值,可以任意次数添加到结果中,并且不能改变结果(例如,0表示加法,1表示乘法)。

>>> rdd = sc.parallelize([("a", 1), ("b", 1), ("a", 1)])
>>> from operator import add
>>> sorted(rdd.foldByKey(0, add).collect())
[('a', 2), ('b', 1)]

24.foreach(f)
将一个函数应用于此RDD的所有元素。

>>> def f(x): print(x)
>>> sc.parallelize([1, 2, 3, 4, 5]).foreach(f)

25.foreachPartition(f)
将一个函数应用于此RDD的每个分区。

>>> def f(iterator):
...     for x in iterator:
...          print(x)
>>> sc.parallelize([1, 2, 3, 4, 5]).foreachPartition(f)

26.fullOuterJoin(other, numPartitions=None)
执行self和other的右外连接。对于self中的每个元素(k, v),RDD要么包含其他元素中w的所有对(k, (v, w)),要么包含其他元素中没有键k的对(k, (v, None))。
类似地,对于other中的每个元素(k, w),结果RDD要么包含所有对(k, (v, w)),要么包含对(k, (None, w)),表示self中的没有key k。最后将RDD分区为numPartitions数量的分区。

>>> x = sc.parallelize([("a", 1), ("b", 4)])
>>> y = sc.parallelize([("a", 2), ("c", 8)])
>>> sorted(x.fullOuterJoin(y).collect())
[('a', (1, 2)), ('b', (4, None)), ('c', (None, 8))]

27.getCheckpointFile()
获取此RDD被checkpoint的文件的名称,如果RDD是本地checkpoint的,则没有被定义。
28.getNumPartitions()

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

29.getStorageLevel()
获取RDD的存储级别

>>> rdd1 = sc.parallelize([1,2])
>>> rdd1.getStorageLevel()
StorageLevel(False, False, False, False, 1)
>>> print(rdd1.getStorageLevel())
Serialized 1x Replicated

30.glom()
返回将每个分区中的元素合并到一个列表中创建的RDD。

>>> rdd = sc.parallelize([1, 2, 3, 4], 2)
>>> sorted(rdd.glom().collect())
[[1, 2], [3, 4]]

31.groupBy(f, numPartitions=None, partitionFunc=<function portable_hash>)
返回分组后的RDD

>>> rdd = sc.parallelize([1, 1, 2, 3, 5, 8])
>>> result = rdd.groupBy(lambda x: x % 2).collect()
>>> sorted([(x, sorted(y)) for (x, y) in result])
[(0, [2, 8]), (1, [1, 1, 3, 5])]

32.groupByKey(numPartitions=None, partitionFunc=<function portable_hash>)
将RDD中每个键的value分组为单个序列。使用numpartition分区对结果RDD进行哈希分区。
如果想要对每个键执行聚合(例如求和或平均值)而进行分组,那么使用reduceByKey或aggregateByKey将提供更好的性能。

>> rdd = sc.parallelize([("a", 1), ("b", 1), ("a", 1)])
>>> sorted(rdd.groupByKey().mapValues(len).collect())
[('a', 2), ('b', 1)]
>>> sorted(rdd.groupByKey().mapValues(list).collect())
[('a', [1, 1]), ('b', [1])]

33.groupWith(other, *others)
支持多个RDD

>>> w = sc.parallelize([("a", 5), ("b", 6)])
>>> x = sc.parallelize([("a", 1), ("b", 4)])
>>> y = sc.parallelize([("a", 2)])
>>> z = sc.parallelize([("b", 42)])
>>> [(x, tuple(map(list, y))) for x, y in sorted(list(w.groupWith(x, y, z).collect()))]
[('a', ([5], [1], [2], [])), ('b', ([6], [4], [], [42]))]

34.histogram(buckets)
使用提供的区间计算直方图。所有的区间都向右打开,只有最后一个区间是关闭的。例如,[1,10,20,50]表示区间是[1,10][10,20][20,50],这意味着1<=x<10, 10<=x<20, 20<=x<=50。在输入1和50的情况下,直方图是1 0 1。
如果您的直方图是等间距的(例如[0,10,20,30]),那么可以将每个元素的O(log n)插入转换为O(1)(其中n是区间的数量)。
bucket必须排序,不包含任何重复项,并且至少有两个元素。
如果bucket是一个数字,它将生成桶,桶是RDD的最小值和最大值之间的均匀间隔。例如,如果最小值为0,最大值为100,给定bucket为2,得到的bucket将是[0,50][50,100]。桶必须至少为1。如果RDD包含无穷大,则会引发异常。如果RDD中的元素没有变化(max == min),那么将使用单个bucket。
返回值是bucket和直方图的元组。

>>> rdd = sc.parallelize(range(51))
>>> rdd.histogram(2)
([0, 25, 50], [25, 26])
>>> rdd.histogram([0, 5, 25, 50])
([0, 5, 25, 50], [5, 20, 26])
>>> rdd.histogram([0, 15, 30, 45, 60])  # evenly spaced buckets
([0, 15, 30, 45, 60], [15, 15, 15, 6])
>>> rdd = sc.parallelize(["ab", "ac", "b", "bd", "ef"])
>>> rdd.histogram(("a", "b", "c"))
(('a', 'b', 'c'), [2, 2])

35.id()
RDD的独特id(在sparkcontext中)
36.intersection(other)
返回这个RDD和另一个RDD的交集。即使输入RDDs包含任何重复的元素,输出也不会包含任何重复的元素。

>>> rdd1 = sc.parallelize([1, 10, 2, 3, 4, 5])
>>> rdd2 = sc.parallelize([1, 6, 2, 3, 7, 8])
>>> rdd1.intersection(rdd2).collect()
[1, 2, 3]

37.isCheckpointed()
返回该RDD是否被checkpoint和materialized,是可靠的还是本地的。
38.isEmpty()

>>> sc.parallelize([]).isEmpty()
True
>>> sc.parallelize([1]).isEmpty()
False

39.isLocallyCheckpointed()
返回这个RDD是否被标记为本地checkpoint
40.join(other, numPartitions=None)
返回一个RDD,该RDD包含在self和other中具有匹配键的所有对元素。
每一对元素将以(k, (v1, v2))元组的形式返回,其中(k, v1)在self中,(k, v2)在other中。
跨集群执行hash连接。

>>> x = sc.parallelize([("a", 1), ("b", 4)])
>>> y = sc.parallelize([("a", 2), ("a", 3)])
>>> sorted(x.join(y).collect())
[('a', (1, 2)), ('a', (1, 3))]

41.keyBy(f)
在RDD应用f创建包含元素的tuple,这里key由f生成。

>>> x = sc.parallelize(range(0,3)).keyBy(lambda x: x*x)
>>> y = sc.parallelize(zip(range(0,5), range(0,5)))
>>> [(x, list(map(list, y))) for x, y in sorted(x.cogroup(y).collect())]
[(0, [[0], [0]]), (1, [[1], [1]]), (2, [[], [2]]), (3, [[], [3]]), (4, [[2], [4]])]

42.keys()

>>> m = sc.parallelize([(1, 2), (3, 4)]).keys()
>>> m.collect()
[1, 3]

43.leftOuterJoin(other, numPartitions=None)
执行self和other的左外连接。
对于self中的每个元素(k, v),结果RDD要么包含其他元素中w的所有对(k, (v, w)),要么包含其他元素中没有键k的对(k, (v, None))。
将结果RDD分区为给定数量的分区。

>>> x = sc.parallelize([("a", 1), ("b", 4)])
>>> y = sc.parallelize([("a", 2)])
>>> sorted(x.leftOuterJoin(y).collect())
[('a', (1, 2)), ('b', (4, None))]

44.localCheckpoint()
使用Spark现有的缓存层将此RDD标记为本地checkpoint。
此方法适用于希望截断RDD联系,同时跳过在可靠的分布式文件系统中复制具体数据的昂贵步骤。这对于具有需要定期截断的长联系的RDDs非常有用(例如GraphX)。

本地检查点牺牲了性能的容错性。特别是,将检查点数据写入executor中的临时本地存储,而不是写入可靠的、容错的存储。其结果是,如果执行程序在计算期间失败,则检查点数据可能不再可访问,从而导致不可恢复的作业失败。

这对于动态分配来说是不安全的,因为动态分配会删除执行器及其缓存块。如果必须同时使用这两个特性,建议您设置spark.dynamicAllocation.cachedExecutorIdleTimeout设置为一个高值。
SparkContext.setCheckpointDir()设置的checkpoint目录设置没有使用。
45.lookup
返回key key在RDD中的值列表。如果RDD有一个已知的分区程序,则只需搜索键映射到的分区,就可以有效地完成此操作。

>>> l = range(1000)
>>> rdd = sc.parallelize(zip(l, l), 10)
>>> rdd.lookup(42)  # slow
[42]
>>> sorted = rdd.sortByKey()
>>> sorted.lookup(42)  # fast
[42]
>>> sorted.lookup(1024)
[]
>>> rdd2 = sc.parallelize([(('a', 'b'), 'c')]).groupByKey()
>>> list(rdd2.lookup(('a', 'b'))[0])
['c']

46.map(f, preservesPartitioning=False)

>>> rdd = sc.parallelize(["b", "a", "c"])
>>> sorted(rdd.map(lambda x: (x, 1)).collect())
[('a', 1), ('b', 1), ('c', 1)]

47.mapPartitions(f, preservesPartitioning=False)
针对每一个分区执行func

>>> rdd = sc.parallelize([1, 2, 3, 4], 2)
>>> def f(iterator): yield sum(iterator)
>>> rdd.mapPartitions(f).collect()
[3, 7]

48.mapPartitionsWithIndex(f, preservesPartitioning=False)
通过对这个RDD的每个分区应用一个函数来返回一个新的RDD,同时应用原始分区的索引。

>>> rdd = sc.parallelize([1, 2, 3, 4], 4)
>>> def f(splitIndex, iterator): yield splitIndex
>>> rdd.mapPartitionsWithIndex(f).sum()
6

49.mapPartitionsWithSplit(f, preservesPartitioning=False)
被移除:以后使用mapPartitionsWithIndex。
通过对这个RDD的每个分区应用一个函数来返回一个新的RDD,同时跟踪原始分区的索引。
50.mapValues(f)

>>> x = sc.parallelize([("a", ["apple", "banana", "lemon"]), ("b", ["grapes"])])
>>> def f(x): return len(x)
>>> x.mapValues(f).collect()
[('a', 3), ('b', 1)]

51.max(key=None)
参数:key

>>> rdd = sc.parallelize([1.0, 5.0, 43.0, 10.0])
>>> rdd.max()
43.0
>>> rdd.max(key=str)55.0

52.mean()

>>> sc.parallelize([1, 2, 3]).mean()
2.0

53.meanApprox(timeout, confidence=0.95)
近似操作,在一个超时内或满足置信度时返回平均值。

>>> rdd = sc.parallelize(range(1000), 10)
>>> r = sum(range(1000)) / 1000.0
>>> abs(rdd.meanApprox(1000) - r) / r < 0.05
True

54.min(key=None)

>>> rdd = sc.parallelize([2.0, 5.0, 43.0, 10.0])
>>> rdd.min()
2.0
>>> rdd.min(key=str)
10.0

55.name()
返回RDD的name
56.partitionBy(numPartitions, partitionFunc=<function portable_hash>)
使用指定的分区返回一个RDD分区的copy

>>> pairs = sc.parallelize([1, 2, 3, 4, 2, 4, 1]).map(lambda x: (x, x))
>>> sets = pairs.partitionBy(2).glom().collect()
>>> len(set(sets[0]).intersection(set(sets[1])))
0

57.persist(storageLevel=StorageLevel(False, True, False, False, 1))
设置此RDD的存储级别,使其值在第一次计算之后跨操作持久化。只有在RDD还没有设置存储级别时,才可以使用它来分配新的存储级别。如果没有指定存储级别,则默认为(MEMORY_ONLY)。

>>> rdd = sc.parallelize(["b", "a", "c"])
>>> rdd.persist().is_cached
True

58.pipe(command, env=None, checkCode=False)
通过管道将元素创建的RDD返回到分叉的外部流程。checkCode表示是否查看shell命令行的返回值。

>>> sc.parallelize(['1', '2', '', '3']).pipe('cat').collect()
['1', '2', '', '3']

59.randomSplit(weights, seed=None)
使用提供的权重随机分割这个RDD。

>>> rdd = sc.parallelize(range(500), 1)
>>> rdd1, rdd2 = rdd.randomSplit([2, 3], 17)
>>> len(rdd1.collect() + rdd2.collect())
500
>>> 150 < rdd1.count() < 250
True
>>> 250 < rdd2.count() < 350
True

60.reduce(f)
使用指定的交换和关联二进制操作符reduce此RDD的元素。当前在本地reduce分区。

>>> from operator import add
>>> sc.parallelize([1, 2, 3, 4, 5]).reduce(add)
15
>>> sc.parallelize((2 for _ in range(10))).map(lambda x: 1).cache().reduce(add)
10
>>> sc.parallelize([]).reduce(add)
Traceback (most recent call last):
    ...
ValueError: Can not reduce() empty RDD

61.reduceByKey(func, numPartitions=None, partitionFunc=<function portable_hash>)
使用联合和可交换的reduce函数合并每个键的值。
在将结果发送到reduce之前,这也将在每个映射器上本地执行合并,类似于MapReduce中的“combiner”。
输出将使用numPartitions分区,如果没有指定numpartition,则使用默认的并行度级别。默认的分区器是哈希分区。

>>> from operator import add
>>> rdd = sc.parallelize([("a", 1), ("b", 1), ("a", 1)])
>>> sorted(rdd.reduceByKey(add).collect())
[('a', 2), ('b', 1)]

62.reduceByKeyLocally(func)
使用关联性和交换性的reduce函数合并每个键的值,但立即将结果作为字典返回给主键。

在将结果发送到reducer之前,这也将在每个映射器上本地执行合并,类似于MapReduce中的“合并器”。

>>> from operator import add
>>> rdd = sc.parallelize([("a", 1), ("b", 1), ("a", 1)])
>>> sorted(rdd.reduceByKeyLocally(add).items())
[('a', 2), ('b', 1)]

63.repartition(numPartitions)
返回一个新的RDD,该RDD具有精确的numPartitions。
可以增加或减少这个RDD中的并行度。在内部,这使用了一个shuffle重新分配数据。如果要减少这个RDD中的分区数量,可以考虑使用coalesce,它可以避免执行shuffle。

>>> rdd = sc.parallelize([1,2,3,4,5,6,7], 4)
>>> sorted(rdd.glom().collect())
[[1], [2, 3], [4, 5], [6, 7]]
>>> len(rdd.repartition(2).glom().collect())
2
>>> len(rdd.repartition(10).glom().collect())
10

64.repartitionAndSortWithinPartitions(numPartitions=None, partitionFunc=<function portable_hash>, ascending=True, keyfunc=<function RDD.<lambda>>)
根据给定的分区和函数重新划分RDD,并在每个结果分区中根据键对记录进行排序。

>>> rdd = sc.parallelize([(0, 5), (3, 8), (2, 6), (0, 8), (3, 8), (1, 3)])
>>> rdd2 = rdd.repartitionAndSortWithinPartitions(2, lambda x: x % 2, True)
>>> rdd2.glom().collect()
[[(0, 5), (0, 8), (2, 6)], [(1, 3), (3, 8), (3, 8)]]

65.rightOuterJoin(other, numPartitions=None)
对于other中的每个元素(k, w):

  • 对于self中的k的值v==>(k, (v, w))
  • self中的任何元素都没有密钥 k==>(k, (None, w)).
>>> x = sc.parallelize([("a", 1), ("b", 4)])
>>> y = sc.parallelize([("a", 2)])
>>> sorted(y.rightOuterJoin(x).collect())
[('a', (2, 1)), ('b', (None, 4))]

66.sample(withReplacement, fraction, seed=None)
返回这个RDD的一个采样子集。参数与Python类似

>>> rdd = sc.parallelize(range(100), 4)
>>> 6 <= rdd.sample(False, 0.1, 81).count() <= 14
True

67.sampleByKey(withReplacement, fractions, seed=None)
返回按key采样的RDD的一个子集(通过分层采样)。

>>> fractions = {"a": 0.2, "b": 0.1}
>>> rdd = sc.parallelize(fractions.keys()).cartesian(sc.parallelize(range(0, 1000)))
>>> sample = dict(rdd.sampleByKey(False, fractions, 2).groupByKey().collect())
>>> 100 < len(sample["a"]) < 300 and 50 < len(sample["b"]) < 150
True
>>> max(sample["a"]) <= 999 and min(sample["a"]) >= 0
True
>>> max(sample["b"]) <= 999 and min(sample["b"]) >= 0
True

68.sampleStdev()
计算此RDD元素的样本标准差(通过除以N-1而不是N来纠正估计标准差时的偏差)。

>>> sc.parallelize([1, 2, 3]).sampleStdev()
1.0

69.sampleVariance()
计算该RDD元素的样本方差(通过除以N-1而不是N来纠正估计方差时的偏差)。

>>> sc.parallelize([1, 2, 3]).sampleVariance()
1.0

70.saveAsHadoopDataset(conf, keyConverter=None, valueConverter=None)
使用旧的Hadoop OutputFormat API (mapred包)将键值对(RDD[(K, V)])的Python RDD输出到任何Hadoop文件系统。使用用户指定的转换器或默认的org.apache.spark.api.python.JavaToWritableConverter为输出转换键/值。
71.saveAsHadoopFile(path, outputFormatClass, keyClass=None, valueClass=None, keyConverter=None, valueConverter=None, conf=None, compressionCodecClass=None)
使用旧的Hadoop OutputFormat API (mapred包)将键值对(RDD[(K, V)])的Python RDD输出到任何Hadoop文件系统。如果未指定,将推断键和值类型。使用用户指定的转换器或org.apache.spark.api.python.JavaToWritableConverter为输出转换键和值。conf应用于与此RDD的SparkContext相关联的基础Hadoop conf之上,以创建用于保存数据的合并Hadoop MapReduce作业配置。
参数

  • path-- Hadoop文件的路径
  • outputFormatClass-- 完全限定的Hadoop OutputFormat类名(例如org.apache. Hadoop .map . sequencefileoutputformat)
  • key可写类的完全限定类名org.apache.hadoop.io.IntWritable。默认None)
  • valueClass-- 值可写类的完全限定类名org.apache.hadoop.io.Text。默认None)

72.saveAsNewAPIHadoopDataset(conf, keyConverter=None, valueConverter=None)
使用新的Hadoop OutputFormat API (mapreduce包)将键值对(RDD[(K, V)])的Python RDD输出到任何Hadoop文件系统。使用用户指定的转换器或默认的org.apache.spark.api.python.JavaToWritableConverter为输出转换键/值。
参数

  • Hadoop作业配置,以dict的形式传入
  • key转换器(默认无)
  • valueConverter -(默认无)

73.saveAsNewAPIHadoopFile(path, outputFormatClass, keyClass=None, valueClass=None, keyConverter=None, valueConverter=None, conf=None)
使用新的Hadoop OutputFormat API (mapreduce包)将键值对(RDD[(K, V)])的Python RDD输出到任何Hadoop文件系统。如果未指定,将推断键和值类型。使用用户指定的转换器或org.apache.spark.api.python.JavaToWritableConverter为输出转换键和值。conf应用于与此RDD的SparkContext相关联的基础Hadoop conf之上,以创建用于保存数据的合并Hadoop MapReduce作业配置。
参数:

  • path- Hadoop文件的路径
  • outputFormatClass- 完全限定的Hadoop OutputFormat类名(例如org.apache. Hadoop .mapreduce.lib.outpu.sequencefileoutputformat)
  • keyClass密钥可写类的完全限定类名(例如org.apache.hadoop.io.IntWritable)
  • valueClass——值可写类的完全限定类名(例如,org.apache.hadoop.io.Text)
    74.saveAsPickleFile(path, batchSize=10)
    将此RDD保存为序列化对象的序列文件。使用的序列化器是pyspark.serializers.PickleSerializer,默认批处理大小为10。
>>> tmpFile = NamedTemporaryFile(delete=True)
>>> tmpFile.close()
>>> sc.parallelize([1, 2, 'spark', 'rdd']).saveAsPickleFile(tmpFile.name, 3)
>>> sorted(sc.pickleFile(tmpFile.name, 5).map(str).collect())
['1', '2', 'rdd', 'spark']

75.saveAsSequenceFile(path, compressionCodecClass=None)
使用org.apache.hadoop.io.Writable将一个键值对(形式RDD[(K, V)])的Python RDD输出到任何Hadoop文件系统。我们从RDD的键和值做类型转换。机制如下:

  • Pyrolite用于将pickle的Python RDD转换为Java对象的RDD。
  • 这个Java RDD的键和值被转换为可写的并被写出来。
    参数
  • path-- 序列文件的路径
  • compressionCodecClass -None

76.saveAsTextFile(path, compressionCodecClass=None)
使用元素的字符串表示形式将此RDD保存为文本文件。
参数
path——文本文件的路径
compressionCodecClass -(默认无)如果是字符串则是org.apache.hadoop.io. compression . gzipcodec

>>> tempFile = NamedTemporaryFile(delete=True)
>>> tempFile.close()
>>> sc.parallelize(range(10)).saveAsTextFile(tempFile.name)
>>> from fileinput import input
>>> from glob import glob
>>> ''.join(sorted(input(glob(tempFile.name + "/part-0000*"))))
'0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n'

可以接受空行

>>> tempFile2 = NamedTemporaryFile(delete=True)
>>> tempFile2.close()
>>> sc.parallelize(['', 'foo', '', 'bar', '']).saveAsTextFile(tempFile2.name)
>>> ''.join(sorted(input(glob(tempFile2.name + "/part-0000*"))))
'\n\n\nbar\nfoo\n'

使用压缩代码类

>>> tempFile3 = NamedTemporaryFile(delete=True)
>>> tempFile3.close()
>>> codec = "org.apache.hadoop.io.compress.GzipCodec"
>>> sc.parallelize(['foo', 'bar']).saveAsTextFile(tempFile3.name, codec)
>>> from fileinput import input, hook_compressed
>>> result = sorted(input(glob(tempFile3.name + "/part*.gz"), openhook=hook_compressed))
>>> b''.join(result).decode('utf-8')
'bar\nfoo\n'

77.setName(name)

>>> rdd1 = sc.parallelize([1, 2])
>>> rdd1.setName('RDD1').name()
'RDD1'

78.sortBy(keyfunc, ascending=True, numPartitions=None)

>>> tmp = [('a', 1), ('b', 2), ('1', 3), ('d', 4), ('2', 5)]
>>> sc.parallelize(tmp).sortBy(lambda x: x[0]).collect()
[('1', 3), ('2', 5), ('a', 1), ('b', 2), ('d', 4)]
>>> sc.parallelize(tmp).sortBy(lambda x: x[1]).collect()
[('a', 1), ('b', 2), ('1', 3), ('d', 4), ('2', 5)]

79.sortByKey(ascending=True, numPartitions=None, keyfunc=<function RDD.<lambda>>)

>>> tmp = [('a', 1), ('b', 2), ('1', 3), ('d', 4), ('2', 5)]
>>> sc.parallelize(tmp).sortByKey().first()
('1', 3)
>>> sc.parallelize(tmp).sortByKey(True, 1).collect()
[('1', 3), ('2', 5), ('a', 1), ('b', 2), ('d', 4)]
>>> sc.parallelize(tmp).sortByKey(True, 2).collect()
[('1', 3), ('2', 5), ('a', 1), ('b', 2), ('d', 4)]
>>> tmp2 = [('Mary', 1), ('had', 2), ('a', 3), ('little', 4), ('lamb', 5)]
>>> tmp2.extend([('whose', 6), ('fleece', 7), ('was', 8), ('white', 9)])
>>> sc.parallelize(tmp2).sortByKey(True, 3, keyfunc=lambda k: k.lower()).collect()
[('a', 3), ('fleece', 7), ('had', 2), ('lamb', 5),...('white', 9), ('whose', 6)]

80.stats()
返回一个StatCounter对象,该对象在一个操作中捕获RDD元素的平均值、方差和计数。
81.stdev()
计算这个RDD元素的标准偏差。

>>> sc.parallelize([1, 2, 3]).stdev()
0.816...

82.subtract(other, numPartitions=None)
返回self有other没有的键和值

>>> x = sc.parallelize([("a", 1), ("b", 4), ("b", 5), ("a", 3)])
>>> y = sc.parallelize([("a", 3), ("c", None)])
>>> sorted(x.subtract(y).collect())
[('a', 1), ('b', 4), ('b', 5)]

83.subtractByKey(other, numPartitions=None)
返回self有other没有的键

>>> x = sc.parallelize([("a", 1), ("b", 4), ("b", 5), ("a", 2)])
>>> y = sc.parallelize([("a", 3), ("c", None)])
>>> sorted(x.subtractByKey(y).collect())
[('b', 4), ('b', 5)]

84.sum()

>>> sc.parallelize([1.0, 2.0, 3.0]).sum()
6.0

85.sumApprox(timeout, confidence=0.95)
在超时内返回和或满足置信度的近似操作。

>>> rdd = sc.parallelize(range(1000), 10)
>>> r = sum(range(1000))
>>> abs(rdd.sumApprox(1000) - r) / r < 0.05
True

86.take(num)
取RDD的第一个num元素为例。
它首先扫描一个分区,然后使用该分区的结果来估计其他分区要满足的限制的数量。

>>> sc.parallelize([2, 3, 4, 5, 6]).cache().take(2)
[2, 3]
>>> sc.parallelize([2, 3, 4, 5, 6]).take(10)
[2, 3, 4, 5, 6]
>>> sc.parallelize(range(100), 100).filter(lambda x: x > 90).take(3)
[91, 92, 93]

87.takeOrdered(num, key=None)
按照key=func结果排序并取出结果

>>> sc.parallelize([10, 1, 2, 9, 3, 4, 5, 6, 7]).takeOrdered(6)
[1, 2, 3, 4, 5, 6]
>>> sc.parallelize([10, 1, 2, 9, 3, 4, 5, 6, 7], 2).takeOrdered(6, key=lambda x: -x)
[10, 9, 7, 6, 5, 4]

88.takeSample(withReplacement, num, seed=None)
返回一个指定大小的RDD的子集

>>> rdd = sc.parallelize(range(0, 10))
>>> len(rdd.takeSample(True, 20, 1))
20
>>> len(rdd.takeSample(False, 5, 2))
5
>>> len(rdd.takeSample(False, 15, 3))
10

89.toDebugString()
RDD的描述及其调试的递归依赖项。
90.toLocalIterator()
返回包含此RDD中所有元素的迭代器。迭代器将消耗与RDD中最大分区相同的内存。

>>> rdd = sc.parallelize(range(10))
>>> [x for x in rdd.toLocalIterator()]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

91.top(num, key=None)

>>> sc.parallelize([10, 4, 2, 12, 3]).top(1)
[12]
>>> sc.parallelize([2, 3, 4, 5, 6], 2).top(2)
[6, 5]
>>> sc.parallelize([10, 4, 2, 12, 3]).top(3, key=str)
[4, 3, 2]

92.treeAggregate(zeroValue, seqOp, combOp, depth=2)
以多层树模式聚合此RDD的元素。

>>> add = lambda x, y: x + y
>>> rdd = sc.parallelize([-5, -4, -3, -2, -1, 1, 2, 3, 4], 10)
>>> rdd.treeAggregate(0, add, add)
-5
>>> rdd.treeAggregate(0, add, add, 1)
-5
>>> rdd.treeAggregate(0, add, add, 2)
-5
>>> rdd.treeAggregate(0, add, add, 5)
-5
>>> rdd.treeAggregate(0, add, add, 10)
-5

93.treeReduce(f, depth=2)
以多层树模式reduce此RDD的元素。

>>> add = lambda x, y: x + y
>>> rdd = sc.parallelize([-5, -4, -3, -2, -1, 1, 2, 3, 4], 10)
>>> rdd.treeReduce(add)
-5
>>> rdd.treeReduce(add, 1)
-5
>>> rdd.treeReduce(add, 2)
-5
>>> rdd.treeReduce(add, 5)
-5
>>> rdd.treeReduce(add, 10)
-5

94.union(other)

>>> rdd = sc.parallelize([1, 1, 2, 3])
>>> rdd.union(rdd).collect()
[1, 1, 2, 3, 1, 1, 2, 3]

95.unpersist()
将RDD标记为非持久性的,并从内存和磁盘中删除它的所有块。
96.values()

>>> m = sc.parallelize([(1, 2), (3, 4)]).values()
>>> m.collect()
[2, 4]

97.variance

>>> sc.parallelize([1, 2, 3]).variance()
0.666...

98.zip(other)
将这个RDD与另一个RDD连接起来,返回每个RDD中的第一个元素和第二个元素的键值对。假设两个rds具有相同数量的分区和每个分区中相同数量的元素(例如一个通过另一个上的映射生成)。

>>> x = sc.parallelize(range(0,5))
>>> y = sc.parallelize(range(1000, 1005))
>>> x.zip(y).collect()
[(0, 1000), (1, 1001), (2, 1002), (3, 1003), (4, 1004)]

99.zipWithIndex()
用元素索引zip这个RDD。
排序首先基于分区索引,然后是每个分区内项的排序。所以第一个分区的第一项得到索引0,最后一个分区的最后一项得到最大的索引。
当此RDD包含多个分区时,此方法需要触发一个spark job。

>>> sc.parallelize(["a", "b", "c", "d"], 3).zipWithIndex().collect()
[('a', 0), ('b', 1), ('c', 2), ('d', 3)]

100.zipWithUniqueId()
使用生成的惟一长id zip此RDD。
分区第k个项将得到ids k, n+k, 2*n+k,…,其中n是分区的数量。因此,可能存在差距,但该方法不会触发spark作业,这与zipWithIndex不同。

>>> sc.parallelize(["a", "b", "c", "d", "e"], 3).zipWithUniqueId().collect()
[('a', 0), ('b', 1), ('c', 4), ('d', 2), ('e', 5)]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值