如何将具有 Decimal 的 Spark DataFrame 转换为具有相同精度的 BigDecimal 的 Dataset?

Tim*_*meh 3 scala apache-spark apache-spark-sql apache-spark-dataset

如何以给定精度创建具有 BigDecimal 的 Spark 数据集?请参阅 Spark shell 中的以下示例。您将看到我可以创建具有所需 BigDecimal 精度的 DataFrame,但无法将其转换为数据集。

scala> import scala.collection.JavaConverters._
scala> case class BD(dec: BigDecimal)
scala> val schema = StructType(Seq(StructField("dec", DecimalType(38, 0))))
scala> val highPrecisionDf = spark.createDataFrame(List(Seq(BigDecimal("12345678901122334455667788990011122233"))).map(a => Row.fromSeq(a)).asJava, schema)
highPrecisionDf: org.apache.spark.sql.DataFrame = [dec: decimal(38,0)]
scala> highPrecisionDf.as[BD]
org.apache.spark.sql.AnalysisException: Cannot up cast `dec` from decimal(38,0) to decimal(38,18) as it may truncate
The type path of the target object is:
- field (class: "scala.math.BigDecimal", name: "dec")
- root class: "BD"
You can either add an explicit cast to the input data or choose a higher precision type of the field in the target object;
Run Code Online (Sandbox Code Playgroud)

同样,我无法从使用更高精度 BigDecimal 的案例类创建数据集。

scala> List(BD(BigDecimal("12345678901122334455667788990011122233"))).toDS.show()
+----+
| dec|
+----+
|null|
+----+
Run Code Online (Sandbox Code Playgroud)

有没有办法创建一个包含 BigDecimal 字段的数据集,其精度不同于默认的小数(38,18)?

Jay*_*man 5

默认情况下,spark 会将 case 类中的 Decimal 类型(或 BigDecimal)的模式推断为 DecimalType(38, 18)(请参阅org.apache.spark.sql.types.DecimalType.SYSTEM_DEFAULT

解决方法是将数据集转换为数据框,如下所示

case class TestClass(id: String, money: BigDecimal)

val testDs = spark.createDataset(Seq(
  TestClass("1", BigDecimal("22.50")),
  TestClass("2", BigDecimal("500.66"))
))

testDs.printSchema()

root
 |-- id: string (nullable = true)
 |-- money: decimal(38,18) (nullable = true)
Run Code Online (Sandbox Code Playgroud)

解决方法

import org.apache.spark.sql.types.DecimalType
val testDf = testDs.toDF()

testDf
  .withColumn("money", testDf("money").cast(DecimalType(10,2)))
  .printSchema()

root
 |-- id: string (nullable = true)
 |-- money: decimal(10,2) (nullable = true)
Run Code Online (Sandbox Code Playgroud)

您可以查看此链接以获取更多详细信息https://issues.apache.org/jira/browse/SPARK-18484