2016-07-05 335 views
3

如何在使用databrick spark-xml庫讀取xml文件時禁用科學記數法。 這裏的情景,我的XML文件包含數值,像這樣如何在spark-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> 

任何幫助將非常感激。

+0

如果你想具體格式不使用的號碼。使用所需格式的字符串。 – zero323

+0

感謝您的回覆,但我怎樣才能決定數據類型 – MD51

+0

@ zero323 plz幫我 – MD51

回答

2

isLong功能TypeCast類不能夠預測的數據類型,因爲你的價值「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) 
3

我不完全知道什麼是對所有的點,但我看到的基本上都是兩個選擇:

  • 如果所有字段可以解釋爲大的整數,或者你的目標是讓這些爲整數您使用的類型轉換什麼應該給或多或少你想要什麼沒有的功能顯著損失:

    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")) 
    
  • ,如果你想要呈現的原因特定數字格式可以將數據轉換爲格式化字符串數組:

    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"))