我有一个包含数百万行的大数据框,如下所示:
A B C Eqn
12 3 4 A+B
32 8 9 B*C
56 12 2 A+B*C
如何评估Eqn
列中的表达式?
答案 0 :(得分:4)
您可以创建一个自定义UDF来评估这些算术函数
def evalUDF = udf((a:Int, b:Int, c:Int, eqn:String) => {
val eqnParts = eqn
.replace("A", a.toString)
.replace("B", b.toString)
.replace("C", c.toString)
.split("""\b""")
.toList
val (sum, _) = eqnParts.tail.foldLeft((eqnParts.head.toInt, "")){
case ((runningTotal, "+"), num) => (runningTotal + num.toInt, "")
case ((runningTotal, "-"), num) => (runningTotal - num.toInt, "")
case ((runningTotal, "*"), num) => (runningTotal * num.toInt, "")
case ((runningTotal, _), op) => (runningTotal, op)
}
sum
})
evalDf
.withColumn("eval", evalUDF('A, 'B, 'C, 'Eqn))
.show()
输出:
+---+---+---+-----+----+
| A| B| C| Eqn|eval|
+---+---+---+-----+----+
| 12| 3| 4| A+B| 15|
| 32| 8| 9| B*C| 72|
| 56| 12| 2|A+B*C| 136|
+---+---+---+-----+----+
正如你所看到的那样有效,但是非常脆弱(空间,未知的操作符等会破坏代码)并且不遵守操作顺序(否则最后应该是92)
所以你可以自己编写所有这些或者找一些已经做过的文库(比如https://gist.github.com/daixque/1610753)?
也许性能开销会非常大(特别是你开始使用递归解析器),但至少你可以在数据帧上执行它而不是先收集它
答案 1 :(得分:2)
我认为执行DataFrame内部SQL的唯一方法是先select("Eqn").collect
然后在源数据集上迭代执行SQL。
由于SQL位于DataFrame中,除了对将在Spark执行程序上执行的分布式计算的描述之外,您无法在处理执行程序上的SQL时提交Spark作业。在执行管道中太迟了。您应该回到驱动程序上以便能够提交新的Spark作业,比如执行SQL。
使用驱动程序上的SQL,然后每个SQL获取相应的行,只需withColumn
执行SQL(及其行)。
我认为编写它比开发一个有效的Spark应用程序更容易,但这就是我如何去做。
答案 2 :(得分:0)
我迟到了,以防万一有人在找
然后您可以使用javax.script.ScriptEngineManager
import javax.script.SimpleBindings;
import javax.script.ScriptEngineManager
import java.util.Map
import java.util.HashMap
def calculateFunction = (mathExpression: String, A : Double, B : Double, C : Double ) => {
val vars: Map[String, Object] = new HashMap[String, Object]();
vars.put("A",A.asInstanceOf[Object])
vars.put("B",B.asInstanceOf[Object])
vars.put("C",C.asInstanceOf[Object])
val engine = new ScriptEngineManager().getEngineByExtension("js");
val result = engine.eval(mathExpression, new SimpleBindings(vars));
result.asInstanceOf[Double]
}
val calculateUDF = spark.udf.register("calculateFunction",calculateFunction)
注意::它将处理通用表达式,并且功能强大,但性能却比接受的答案差很多,并且占用大量内存