【发布时间】:2018-09-14 00:25:58
【问题描述】:
Spark Dataframes 有一个方法 withColumn 一次添加一个新列。要添加多个列,需要withColumns 链。这是执行此操作的最佳做法吗?
感觉使用mapPartitions更有优势。假设我有一个由三个withColumns 组成的链,然后一个过滤器根据特定条件删除Rows。这是四种不同的操作(不过,我不确定这些操作是否是广泛的转换)。但如果我做一个mapPartitions,我可以一口气做完。如果我有一个我希望每个 RDD 分区打开一次的数据库连接,这也会有所帮助。
我的问题分为两部分。
第一部分,这是我对 mapPartitions 的实现。这种方法是否有任何不可预见的问题?有没有更优雅的方法来做到这一点?
df2 = df.rdd.mapPartitions(add_new_cols).toDF()
def add_new_cols(rows):
db = open_db_connection()
new_rows = []
new_row_1 = Row("existing_col_1", "existing_col_2", "new_col_1", "new_col_2")
i = 0
for each_row in rows:
i += 1
# conditionally omit rows
if i % 3 == 0:
continue
db_result = db.get_some_result(each_row.existing_col_2)
new_col_1 = ''.join([db_result, "_NEW"])
new_col_2 = db_result
new_f_row = new_row_1(each_row.existing_col_1, each_row.existing_col_2, new_col_1, new_col_2)
new_rows.append(new_f_row)
db.close()
return iter(new_rows)
第二部分,在withColumn 和filter 链上使用mapPartitions 的权衡是什么?
我在某处读到,使用 Spark DF 的可用方法总是比推出自己的实现更好。如果我的论点是错误的,请告诉我。谢谢!欢迎所有想法。
【问题讨论】:
-
你能分享一个你无法解决的问题的例子吗?到目前为止,您的问题太宽泛,有点不清楚。
-
如果您担心的话,
withColumns 链将不会连续执行。惰性火花将优化操作。 -
为了避免两次打开数据库连接,您可以返回一个列表,然后将输出拆分为列。像
df = df.withColumn('list_output', myUDF()).select("*", col('list_output')[0].alias('new_col1'), col('list_output)[1].alias('new_col2')).drop("list_output")这样的东西。转换为 rdd 并返回 DF 很慢,但我不是这方面的专家。 -
@void 看看this post。您也可以花哨并从您的 udf 返回
StructType(),然后使用list_output.*
标签: apache-spark pyspark apache-spark-sql pyspark-sql