如何将多个Pandas DF转换为单个Spark DF?

时间:2017-04-17 18:49:40

标签: pandas apache-spark pyspark

我有几个Excel文件需要在加载到Spark DF之前加载和预处理。我有一个需要处理的这些文件的列表。我这样做是为了阅读它们:

file_list_rdd = sc.emptyRDD()

for file_path in file_list:
    current_file_rdd = sc.binaryFiles(file_path)
    print(current_file_rdd.count())
    file_list_rdd = file_list_rdd.union(current_file_rdd)

然后我有一些mapper函数将file_list_rdd从一组(路径,字节)元组转换为(path,Pandas DataFrame)元组。这允许我使用Pandas来读取Excel文件并操作文件,以便在将它们变成Spark DataFrame之前统一它们。

如何获取(文件路径,Pandas DF)元组的RDD并将其转换为单个Spark DF?我知道可以进行单个转换的函数,但不知道可以执行多个转换的函数。

我的第一次尝试是这样的:

sqlCtx = SQLContext(sc)

def convert_pd_df_to_spark_df(item):
    return sqlCtx.createDataFrame(item[0][1])

processed_excel_rdd.map(convert_pd_df_to_spark_df)

我猜这是行不通的,因为sqlCtx并未与计算一起分配(因为堆栈跟踪没有多大意义,所以猜测它是不可能的对我来说。

提前感谢您花时间阅读:)。

3 个答案:

答案 0 :(得分:0)

为什么不列出数据帧或文件名,然后在循环中调用union。像这样:

如果是pandas dataframes:

dfs = [df1, df2, df3, df4]
sdf = None
for df in dfs:
    if sdf:
        sdf = sdf.union(spark.createDataFrame(df))
    else:
        sdf = spark.createDataFrame(df)

如果是文件名:

names = [name1, name2, name3, name4]
sdf = None
for name in names:
    if sdf:
        sdf = sdf.union(spark.createDataFrame(pd.read_excel(name))
    else:
        sdf = spark.createDataFrame(pd.read_excel(name))

答案 1 :(得分:0)

我通过编写这样的函数来解决这个问题:

def pd_df_to_row(rdd_row):
    key = rdd_row[0]
    pd_df = rdd_row[1]        

    rows = list()
    for index, series in pd_df.iterrows():
        # Takes a row of a df, exports it as a dict, and then passes an unpacked-dict into the Row constructor

        row_dict = {str(k):v for k,v in series.to_dict().items()}
        rows.append(Row(**row_dict))

    return rows

您可以通过调用以下内容来调用它:

processed_excel_rdd = processed_excel_rdd.flatMap(pd_df_to_row)

pd_df_to_row现在有一组Spark Row对象。你现在可以说:

processed_excel_rdd.toDF()

可能比Series更有效 - > dict - > Row操作,但这让我了解了。

答案 2 :(得分:0)

可以通过转换为Arrow RecordBatches来完成,Spark> 2.3可以以非常有效的方式处理成DF。

https://gist.github.com/linar-jether/7dd61ed6fa89098ab9c58a1ab428b2b5

此代码段猴子补丁包含createFromPandasDataframesRDD方法。 createFromPandasDataframesRDD方法接受熊猫DF(假定列相同)的RDD对象,并返回单个Spark DF。