2017-06-22 48 views
0

我以CSV數據使用下面的代碼當前正在閱讀:星火CSV閱讀援引NUMERICS

Dataset<Row> dataset = getSparkSession().read() 
      .option("header", "true") 
      .option("quote", '"') 
      .option("sep", ',') 
      .schema(schema) 
      .csv(path) 
      .toDF(); 

被引導到具有這個樣子行的CSV文件:

"abc","city","123" 

爲以及具有如下行的另一個文件:

"abc","city",123 

第二個工作正常,因爲我傳遞的模式是

string, string, long 

的第一個結果java.lang.NumberFormatException: For input string: "123"

是否有可能爲CSV讀者正確讀取兩種有效格式的CSV?假設選項已通過。

我使用星火2.1.1

回答

1

使用你的代碼實際上是爲我崩潰。我懷疑使用字符而不是字符串是罪魁禍首。使用'"'.toString代替.option("quote",...)可以修復崩潰問題併發揮作用。此外,您可能還想要定義轉義字符,如下面的代碼所示。

在Cloudera的Spark2,我能夠使用以下方法來既引述和無引號號碼解析到DecimalType,與預先定義的模式:解析的數字

spark.read 
      .option("mode", "FAILFAST") 
      .option("escape", "\"") 
      .option("delimiter", DELIMITER) 
      .option("header", HASHEADER.toString) 
      .option("quote", "\"") 
      .option("nullValue", null) 
      .option("ignoreLeadingWhiteSpace", value = true) 
      .schema(SCHEMA) 
      .csv(PATH) 

實例(從單元測試):

1.0 
11 
"15.23" 
"" 
//empty field 
"0.0000000001" 
1111111111111. 
000000000. //with leading space 

這也適用於我的測試IntegerType - 它可以被解析,不管引號如何。

+0

不幸的是,那是我的錯誤。我沒有在我的實際代碼中使用字符。我從我的模式創建類中檢索參數,它將字符串轉換爲字符而不是字符(爲了簡單起見,我不小心使用了'''''而不是'「\」「'。可能是Cloudera的Spark2版本和Java 2.1.1 maven版本的區別 – DeeVu

+0

@DeeVu不,那不是 - 我只是修改了我的build.sbt以使用2.1.1,我的單元測試仍然是綠色的。你是如何定義你的模式的? –

+0

好的。你說得對,這是一個模式問題。我的demoset試圖將我的100列中的一列轉換爲小數時的整數。我可以放心地說我正在把我的頭撞在我的桌子上。 – DeeVu

1

使用inferSchema屬性,它可以自動識別列的數據類型。

var data= sparkSession.read 
     .option("header", hasColumnHeader) 
     .option("inferSchema", "true").csv(inputPath); 
+0

我不能使用inferSchema。它不適用於我所有的客戶端數據集。我們有我們自己的推理模式函數,其指數性地更好地工作。我們檢測到「123」和123都是數字,但我們如何告訴spark數據集忽略引號以避免NFE。 – DeeVu

+0

爲什麼不能在將該列作爲字符串讀取後立即更改該列的數據類型? 你可以使用withColumnRenamed和withColumn api來解決這個問題。 – Varadha31590

+0

我試過了。您不能將字符串列的數據類型更改爲數字列,因爲它會導致出現'java.lang.RuntimeException:java.lang.String不是bigint模式的有效外部類型' – DeeVu