当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Python PySpark RDD map方法用法及代码示例


PySpark RDD 的 map(~) 方法对 RDD 的每个元素应用一个函数。

参数

1. f | function

要应用的函数。

2. preservesPartitioning | boolean | optional

是否让 Spark 假设分区仍然有效。这仅与 PairRDD 相关。请参阅下面的示例以进行说明。默认情况下,preservesPartitioning=False

返回值

PySpark RDD (pyspark.rdd.PipelinedRDD)。

例子

将函数应用于 RDD 的每个元素

使 RDD 中的所有值都小写:

# Create a RDD with 5 partitions
rdd = sc.parallelize(["A","B","C","D","E","F"], numSlices=5)
new_rdd = rdd.map(lambda x: x.lower())
new_rdd.collect()



['a', 'b', 'c', 'd', 'e', 'f']

将map方法应用于RDD时保留分区

preservesPartitioning 参数仅在 RDD 包含元组列表(成对 RDD)时起作用。

当 RDD 通过 partitionBy(~) (使用哈希分区器)重新分区时,我们保证具有相同键的元组最终位于同一分区中:

rdd = sc.parallelize([("A",1),("B",1),("C",1),("A",1),("D",1)], numSlices=3)
new_rdd = rdd.partitionBy(numPartitions=2)
new_rdd.glom().collect()



[[('C', 1)], [('A', 1), ('B', 1), ('A', 1), ('D', 1)]]

事实上,我们看到元组 ('A',1)('A',1) 位于同一分区中。

现在让我们执行 map(~) 操作,并将 preservesPartitioning 设置为 False(默认):

mapped_rdd = new_rdd.map(lambda my_tuple: (my_tuple[0], my_tuple[1]+3))
mapped_rdd.glom().collect()



[[('C', 4)], [('A', 4), ('B', 4), ('A', 4), ('D', 4)]]

在这里,我们应用map(~),它返回一个具有相同键但具有不同值的元组。我们可以看到分区没有改变。然而,在幕后,Spark 内部有一个标志来指示分区是否已被破坏,由于默认设置为 preservesPartitioning=False,因此该标志现在已设置为 True(即分区已被破坏)。 Spark 这样做是天真的,因为元组键没有改变,所以分区应该仍然有效。

我们可以确认 Spark 现在天真地不知道数据是通过执行像 reduceByKey(~) 这样的混洗操作来按元组键分区的:

mapped_rdd_reduced = mapped_rdd.reduceByKey(lambda x: x+y)
print(mapped_rdd_reduced.toDebugString().decode("utf-8"))



(2) PythonRDD[238] at RDD at PythonRDD.scala:58 []
 |  MapPartitionsRDD[237] at mapPartitions at PythonRDD.scala:183 []
 |  ShuffledRDD[236] at partitionBy at <unknown>:0 []
 +-(2) PairwiseRDD[235] at reduceByKey at <command-1339085475381822>:1 []
    |  PythonRDD[234] at reduceByKey at <command-1339085475381822>:1 []
    |  MapPartitionsRDD[223] at mapPartitions at PythonRDD.scala:183 []
    |  ShuffledRDD[222] at partitionBy at <unknown>:0 []
    +-(3) PairwiseRDD[221] at partitionBy at <command-1339085475381815>:2 []
       |  PythonRDD[220] at partitionBy at <command-1339085475381815>:2 []
       |  ParallelCollectionRDD[219] at readRDDFromInputStream at PythonRDD.scala:413 []

可以看到确实发生了洗牌。然而,这是完全没有必要的,因为我们知道具有相同键的元组位于同一分区(机器)中,因此该操作可以在本地完成。

现在,考虑当我们将 preservesPartitioning 设置为 True 时的情况:

mapped_rdd_preserved = new_rdd.map(lambda my_tuple: (my_tuple[0], my_tuple[1]+3), preservesPartitioning=True)
mapped_rdd_preserved_reduced = mapped_rdd_preserved.reduceByKey(lambda x: x+y)
print(mapped_rdd_preserved_reduced.toDebugString().decode("utf-8"))



(2) PythonRDD[239] at RDD at PythonRDD.scala:58 []
 |  MapPartitionsRDD[223] at mapPartitions at PythonRDD.scala:183 []
 |  ShuffledRDD[222] at partitionBy at <unknown>:0 []
 +-(3) PairwiseRDD[221] at partitionBy at <command-1339085475381815>:2 []
    |  PythonRDD[220] at partitionBy at <command-1339085475381815>:2 []
    |  ParallelCollectionRDD[219] at readRDDFromInputStream at PythonRDD.scala:413 []

我们可以看到没有发生洗牌。这是因为我们告诉 Spark 我们只更改了元组的值,而不是键,因此 Spark 应该假设原始分区保持不变。

相关用法


注:本文由纯净天空筛选整理自Isshin Inada大神的英文原创作品 PySpark RDD | map method。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。