我之前已经将Dataset [T]写入了csv文件。

在这种情况下,T是一个包含字段x的案例类:Option [BigDecimal]

当我尝试将文件加载回Dataset [T]时,看到以下错误:

Exception in thread "main" org.apache.spark.sql.AnalysisException: Cannot up cast `x` from double to decimal(38,18) as it may truncate.

我猜想原因是推断的架构包含一个double而不是BigDecimal列。有没有解决这个问题的方法?我希望避免基于列名进行强制转换,因为读取的代码是泛型函数的一部分。我的阅读代码如下:
   val a = spark
    .read
    .format("com.databricks.spark.csv")
    .option("header", "true")
    .option("inferSchema", "true")
    .load(file)
    .as[T]

我的案例类反映了从JDBC读取的带有Option[T]的表,这些表用于表示可为空的字段。 Option[BigDecimal]用于从JDBC接收Decimal字段。

在本地计算机上进行读写时,我使用了一些代码来从csv文件中进行读写。因此,我可以轻松地检查内容。

所以我的下一个尝试是:
   var df = spark
    .read
    .format("com.databricks.spark.csv")
    .option("header", "true")
    .schema(implicitly[Encoder[T]].schema)
    .load(file)

  val schema = df.schema

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

  schema.foreach{ field =>
    field.dataType match {
      case t: DoubleType =>
        df = df.withColumn(field.name,
          col(field.name).cast(DecimalType(38,18)))
      case _ => // do nothing
    }
  }

  df.as[T]

不幸的是,我的case类现在包含所有None而不是预期的值。如果我只是将csv作为具有推断类型的DF加载,则所有列值均已正确填充。

看来我实际上有两个问题。
  • 从Double-> BigDecimal转换。
  • 可空字段未包装在“选项”中。

  • 任何帮助/建议将不胜感激。如果很容易从csv文件中写入/读取Option / BigDecimals,那么很乐意调整我的方法。

    最佳答案

    首先,我将用dfB.na.fill(0.0)填充空值,然后尝试下一个解决方案:

    case class MyCaseClass(id: String, cost: Option[BigDecimal])
    var dfB = spark.createDataset(Seq(
      ("a", Option(12.45)),
      ("b", Option(null.asInstanceOf[Double])),
      ("c", Option(123.33)),
      ("d", Option(1.3444))
    )).toDF("id", "cost")
    
    dfB
      .na.fill(0.0)
      .withColumn("cost", col("cost").cast(DecimalType(38,18)))
      .as[MyCaseClass]
      .show()
    

    首先将列成本显式转换为DecimalType(38,18),然后检索数据集[MyCaseClass]。我认为这里的问题是,如果不明确指定比例精度,则火花无法将double转换为BigDecimal,因此您需要首先将其转换为特定的十进制类型,然后将其用作BigDecimal。

    更新:
    我稍微修改了前面的代码,以使其也可以处理Option [BigDecimal]类型的成员

    祝好运

    关于apache-spark-sql - Spark SQL-将csv读入Dataset [T],其中T是Option [BigDecimal]字段的案例类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49491161/

    10-16 03:30