在将rdd转换为dataframe

时间:2016-11-22 16:51:15

标签: python apache-spark pyspark apache-spark-sql

我很困惑为什么在将生成的RDD转换为DataFrame时,Spark正在使用rdd.mapPartitions的1个任务。

这对我来说是一个问题,因为我想从:

DataFrame - > RDD - > rdd.mapPartitions - > DataFrame

这样我就可以读取数据(DataFrame),将非SQL函数应用于数据块(RDD上的mapPartitions),然后转换回DataFrame,以便我可以使用DataFrame.write进程。

我可以从DataFrame转发 - > mapPartitions然后使用像saveAsTextFile这样的RDD编写器,但这不太理想,因为DataFrame.write进程可以执行诸如以Orc格式覆盖和保存数据之类的操作。所以我想学习为什么这是正在进行的,但从实际的角度来看,我主要关心的是能够从数据框中去 - > mapParitions - >使用DataFrame.write进程。

这是一个可重复的例子。以下按预期工作,mapPartitions工作有100个任务:

from pyspark.sql import SparkSession
import pandas as pd

spark = SparkSession \
    .builder \
    .master("yarn-client") \
    .enableHiveSupport() \
    .getOrCreate()

sc = spark.sparkContext

df = pd.DataFrame({'var1':range(100000),'var2': [x-1000 for x in range(100000)]})
spark_df = spark.createDataFrame(df).repartition(100)

def f(part):
    return [(1,2)]

spark_df.rdd.mapPartitions(f).collect()

但是,如果最后一行更改为spark_df.rdd.mapPartitions(f).toDF().show(),那么mapPartitions工作只会有一项任务。

一些截图说明如下: enter image description here enter image description here

1 个答案:

答案 0 :(得分:6)

DataFrame.show()仅显示数据帧的第一行数,默认情况下仅显示前20行。如果该数字小于每个分区的行数,则Spark是惰性的,仅评估单个分区,相当于一项任务。

您还可以对数据框执行collect,以计算和收集所有分区,并再次查看100个任务。

您仍然会像以前一样首先看到runJob任务,这是由toDF调用导致的,以便能够确定生成的数据帧架构:它需要处理单个分区才能够确定映射函数的输出类型。在此初始阶段之后,collect等实际操作将在所有分区上发生。例如,对于我运行您的代码段,最后一行替换为spark_df.rdd.mapPartitions(f).toDF().collect()会产生以下阶段:

enter image description here