如何在spark-xml中禁用科学计数法

3
如何在使用databrick spark-xml库读取xml文件时禁用科学计数法。 下面是一个场景:我的XML文件中包含带有空格的数字值,就像这样。
<V1>42451267 </V1>

我得到的是4.2451267E7,而不是42451267,如何修复它?

以下是我的代码和xml文件:

val xmlLocation = "sampleFile/xml/sample.xml"
val rootTag = "RTS"
val rowTag = "COLUMNTYPE"
val sqlContext = MySparkDriver.getSqlContext().
  read.format("com.databricks.spark.xml")
if (rootTag != null && rootTag.size == 0)
  sqlContext.option("rootTag", rootTag)
sqlContext.option("rowTag", rowTag)
val xmlDF = sqlContext.load(xmlLocation)
xmlDF.show(false)

输出

[WrappedArray(4232323.0, 4.2451267E7),21-11-2000 01:04:34,NTS,212212112,100.0,100.0]

期望的

[WrappedArray(4232323, 42451267),21-11-2000 01:04:34,NTS,212212112,100.0000,100.0000]

XML文件

<RTS>
<COLUMNTYPE>
    <D1>
        <V1>4232323</V1>
        <V1>42451267 </V1>
        <V2>21-11-2000 01:04:34</V2>
        <V3>NTS</V3>
        <V4>212212112</V4>
        <V7>100.0000</V7>
        <V8>100.0000 </V8>

    </D1>
</COLUMNTYPE>
</RTS>

任何帮助都将不胜感激。

如果您想要特定的格式,请勿使用数字。请使用带有所需格式的字符串。 - zero323
谢谢您的回复,但我该如何决定数据类型? - MD51
@zero323 请帮帮我。 - MD51
2个回答

3

我不太确定所有这些的目的是什么,但我基本上看到两个选择:

  • if all fields can be interpreted as big integer or you goal is to have these as integers you use type casting what should give more or less what you want without significant loss of functionality:

    case class D1(
      v1: Seq[Double], v2: String, v3: String, v4: Long, v7: Double, v8: Double
    )
    case class ColumnType(d1: D1)
    
    val df = Seq(ColumnType(D1(
      Seq(4232323, 42451267), 
      "21-11-2000 01:04:34",
      "NTS",
      212212112,
      100.0000,
      100.0000
    ))).toDF()
    
    df.select(struct(
      $"d1.v1".cast("array<bigint>").alias("v1"),
      $"d1.v2", $"d1.v3", $"d1.v4", $"d1.v7", $"d1.v8"
    ).alias("d1"))
    
  • if you want a specific number format for presentation reasons you can convert data to an array of formated strings:

    val toFormatted = udf((xs: Seq[Double]) => xs.map(x => f"$x%4.0f"))
    
    df.select(struct(
      toFormatted($"d1.v1").alias("v1"),
      $"d1.v2", $"d1.v3", $"d1.v4", $"d1.v7", $"d1.v8"
    ).alias("d1"))
    

2

TypeCast类的isLong函数无法预测数据类型,因为您的值"42451267 "包含空格。

然而,如果您想将其视为长整型值,则需要定义自己的自定义模式,其中“V1”列的数据类型为StringType。

val xmlLocation = "sampleFile/xml/sample.xml"
val rootTag = "RTS"
val rowTag = "COLUMNTYPE"
val sqlContext = MySparkDriver.getSqlContext().
  read.format("com.databricks.spark.xml")
if (rootTag != null && rootTag.size == 0)
  sqlContext.option("rootTag", rootTag)
sqlContext.option("rowTag", rowTag)

自定义模式

val customSchema = StructType(Array(
  StructField("D1", StructType(
    Seq(StructField("V1", ArrayType(StringType, true), true),
      StructField("V2", StringType, true),
      StructField("V3", StringType, true),
      StructField("V4", LongType, true),
      StructField("V7", DoubleType, true),
      StructField("V8", DoubleType, true))), true)))
sqlContext.schema(customSchema)

创建用于修剪值的UDF。
import org.apache.spark.sql.functions._
val toTrim = udf((xs: Seq[String]) => xs.map(_.trim()))

将UDF应用和类型转换为长整型

val xmlDF = sqlContext.load(xmlLocation).select(struct(
  toTrim(col("D1.V1")).cast("array<long>").alias("V1"),
  col("D1.V2"), col("D1.V3"), col("D1.V4"), col("D1.V7"), col("D1.V8"))
  .alias("D1"))
xmlDF.printSchema
xmlDF.show(false)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接