设置 UDF 返回的 DecimalType 的精度
Set precision of DecimalType returned by UDF
我有一个像这样的 DataFrame :
// +---------+-----------+
// | 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
添加 return 类型来解决
您可以定义具有指定 return 类型的 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|
+--------+--------------------------------+
我有一个像这样的 DataFrame :
// +---------+-----------+
// | 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
添加 return 类型来解决您可以定义具有指定 return 类型的 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|
+--------+--------------------------------+