我在 spark 中有一个操作,应该对数据框中的几列执行。通常,有 2 种可能性来指定此类操作
- 硬编码
handleBias("bar", df)
.join(handleBias("baz", df), df.columns)
.drop(columnsToDrop: _*).show
- 从列名列表动态生成它们
var isFirst = true
var res = df
for (col <- columnsToDrop ++ columnsToCode) {
if (isFirst) {
res = handleBias(col, res)
isFirst = false
} else {
res = handleBias(col, res)
}
}
res.drop(columnsToDrop: _*).show
问题是动态生成的 DAG 是不同的,并且当使用更多列时,动态解决方案的运行时间会比硬编码操作增加得更多。
我很好奇如何将动态构造的优雅与快速执行时间结合起来。
对于大约 80 列,这为硬编码的变体生成了一个相当不错的图形,
并且对于动态构造的查询来说,这是一个非常大的、可能不太可并行化且速度较慢的 DAG。
当前版本的 spark (2.0.2)DataFrames
与 spark-sql一起使用
完成最小示例的代码:
def handleBias(col: String, df: DataFrame, target: String = "FOO"): DataFrame = {
val pre1_1 = df
.filter(df(target) === 1)
.groupBy(col, target)
.agg((count("*") / df.filter(df(target) === 1).count).alias("pre_" + col))
.drop(target)
val pre2_1 = df
.groupBy(col)
.agg(mean(target).alias("pre2_" + col))
df
.join(pre1_1, Seq(col), "left")
.join(pre2_1, Seq(col), "left")
.na.fill(0)
}
编辑
运行您的任务会foldleft
生成一个线性 DAG
,并对所有列的函数进行硬编码会导致
两者都比我原来的 DAG 好很多,但硬编码的变体对我来说看起来更好。在 spark 中连接 SQL 语句的字符串可以让我动态生成硬编码的执行图,但这看起来相当难看。你看到任何其他选择吗?