我有几个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
并未与计算一起分配(因为堆栈跟踪没有多大意义,所以猜测它是不可能的对我来说。
提前感谢您花时间阅读:)。
答案 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。