sparkDataframe中的scala求值公式

hmae6n7t  于 2021-07-14  发布在  Spark
关注(0)|答案(2)|浏览(339)

是否可以在引用列的Dataframe中计算公式?e、 g.如果我有这样的数据(scala示例):

val df = Seq(
    ( 1, "(a+b)/d", 1, 20, 2, 3, 1 ),
    ( 2, "(c+b)*(a+e)", 0, 1, 2, 3, 4 ),
    ( 3, "a*(d+e+c)", 7, 10, 6, 2, 1 )
  )
    .toDF( "Id", "formula", "a", "b", "c", "d", "e" )

df.show()

预期结果:

我一直无法得到 selectExpr , expr , eval() 或者它们的组合。

daolsyd0

daolsyd01#

您可以在自定义项中使用scala工具箱评估:

import org.apache.spark.sql.functions.col
import scala.reflect.runtime.universe
import scala.tools.reflect.ToolBox
val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()

val cols = df.columns.tail
val eval_udf = udf(
    (r: Seq[String]) => 
    tb.eval(tb.parse(
        ("val %s = %s;" * cols.tail.size).format(
            cols.tail.zip(r.tail).flatMap(x => List(x._1, x._2)): _*
        ) + r(0)
    )).toString
)

val df2 = df.select(col("id"), eval_udf(array(df.columns.tail.map(col):_*)).as("result"))

df2.show
+---+------+
| id|result|
+---+------+
|  1|     7|
|  2|    12|
|  3|    63|
+---+------+
fjnneemd

fjnneemd2#

一个稍微不同版本的mck的答案,通过替换 formula 列,然后调用eval udf:

import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox

val eval = udf((f: String) => {
  val toolbox = currentMirror.mkToolBox()
  toolbox.eval(toolbox.parse(f)).toString
})

val formulaExpr = expr(df.columns.drop(2).foldLeft("formula")((acc, c) => s"replace($acc, '$c', $c)"))    
df.select($"Id", eval(formulaExpr).as("result")).show()

//+---+------+
//| Id|result|
//+---+------+
//|  1|     7|
//|  2|    12|
//|  3|    63|
//+---+------+

相关问题