设置 UDF 返回的 DecimalType 的精度

时间:2021-05-02 19:37:38

标签: scala apache-spark user-defined-functions

我有一个这样的数据帧:

// +---------+-----------+
// | myString|   myDouble|
// +---------+-----------+
// |AAA      |2.0        |
// |BBB      |3.0        |
// |CCC      |1.0        |
// +---------+-----------+

并且我想将 UDF 应用到我的数据框以将 myDouble 列乘以 BigDecimal,然后得到第三列 myBigDecimal

我的 UDF :

val myUDf : UserDefinedFunction = udf((d : Double) => {
  (BigDecimal.valueOf(d)*BigDecimal("1.100000000000000000000000000001")).setScale(30)
})

然后我应用我的 UDF :

df.withcolumn("myBigDecimal", myUdf(col("myDouble"))

然后我得到第一行:myBigDecimal = 2.200000000000000000 //expected 2.200000000000000000000000000002

我打印了架构,发现 myBigDecimal 的类型是:DecimalType(38,18)

我该怎么做才能得到预期的结果? (30 位数比例)

我尝试投射:

df.withcolumn("myBigDecimal", myUdf(col("myDouble").cast(DecimalType(38,30)))

但是我得到了相同的结果并且架构仍然是 DecimalType(38,18)

编辑:通过向 UDF 添加返回类型来解决

1 个答案:

答案 0 :(得分:1)

您可以定义具有指定返回类型的 UDF:

import org.apache.spark.sql.types._

spark.sql("set spark.sql.legacy.allowUntypedScalaUDF = true")

val myUdf = udf(
    (d : Double) => {(BigDecimal.valueOf(d)*BigDecimal("1.100000000000000000000000000001")).setScale(30)}, 
    DecimalType(38,30)
)

val df = spark.sql("select 2.0d as myDouble")
val df2 = df.withColumn("myBigDecimal", myUdf(col("myDouble")))

df2.show(false)
+--------+--------------------------------+
|myDouble|myBigDecimal                    |
+--------+--------------------------------+
|2.0     |2.200000000000000000000000000002|
+--------+--------------------------------+
相关问题