我使用的是火花2.2。我想规范化固定大小数组中的每个值。
输入
{"values": [1,2,3,4]}
输出
{"values": [0.25, 0.5, 0.75, 1] }
目前,我正在使用 udf :
val f = udf { (l: Seq[Double]) =>
val max = l.max
l.map(_ / max)
}
有没有办法避免使用udf(以及相关的性能损失)。
答案 0 :(得分:2)
让我们说每个数组中的记录数是n
val n: Int
然后
import org.apache.spark.sql.functions._
df
.withColumn("max", greatest((0 until n).map(i => col("value")(i)): _*))
.withColumn("values", array((0 until n).map(i => col("value")(i) / col("max")): _*))
答案 1 :(得分:0)
我已经提出了我的udf的优化版本,它执行就地更新。
val optimizedNormalizeUdf = udf { (l: mutable.WrappedArray[Double]) =>
val max = l.max
(0 until n).foreach(i => l.update(i, l(i) / max))
l
}
我已经编写了一个基准来检查user8838736提出的解决方案的性能。结果如下。
[info] Benchmark Mode Cnt Score Error Units
[info] NormalizeBenchmark.builtin avgt 10 140,293 ± 10,805 ms/op
[info] NormalizeBenchmark.udf_naive avgt 10 104,708 ± 7,421 ms/op
[info] NormalizeBenchmark.udf_optimized avgt 10 99,492 ± 7,829 ms/op
结论:在这种情况下, udf 是性能最佳的解决方案。
PS:对于那些感兴趣的人,基准的源代码在这里:https://github.com/YannMoisan/spark-jmh