2017-08-16 523 views
0

雖然我正在嘗試使用小數類型創建數據框,但它會拋出以下錯誤。創建Dataframe時DecimalType問題

我執行以下步驟:

import org.apache.spark.sql.Row; 
import org.apache.spark.sql.types.StructField; 
import org.apache.spark.sql.types.StructType; 
import org.apache.spark.sql.types.StringType; 
import org.apache.spark.sql.types.DataTypes._; 


//created a DecimalType 
val DecimalType = DataTypes.createDecimalType(15,10) 

//創建的模式沒有任何errors.But是越來越創建

val sch = StructType(StructField("COL1",StringType,true)::StructField("COL2",**DecimalType**,true)::Nil) 

val src = sc.textFile("test_file.txt") 
val row = src.map(x=>x.split(",")).map(x=>Row.fromSeq(x)) 
val df1= sqlContext.createDataFrame(row,sch) 

DF1,當我發出的df1.collect()動作,它給我下面的錯誤:

scala.MatchError: 0 (of class java.lang.String) 
    at org.apache.spark.sql.catalyst.CatalystTypeConverters$DecimalConverter.toCatalystImpl(CatalystTypeConverters.scala:326) 

test_file.txt內容:

test1,0 
test2,0.67 
test3,10.65 
test4,-10.1234567890 

是否有任何問題,我創建DecimalType的方式?

+0

閱讀一切,StringType和投以後DecimalType。 – philantrovert

回答

3

您應該有一個BigDecimal的實例轉換爲DecimalType

val DecimalType = DataTypes.createDecimalType(15, 10) 
val sch = StructType(StructField("COL1", StringType, true) :: StructField("COL2", DecimalType, true) :: Nil) 

val src = sc.textFile("test_file.txt") 
val row = src.map(x => x.split(",")).map(x => Row(x(0), BigDecimal.decimal(x(1).toDouble))) 

val df1 = spark.createDataFrame(row, sch) 
df1.collect().foreach { println } 
df1.printSchema() 

結果看起來是這樣的:

[test1,0E-10] 
[test2,0.6700000000] 
[test3,10.6500000000] 
[test4,-10.1234567890] 
root 
|-- COL1: string (nullable = true) 
|-- COL2: decimal(15,10) (nullable = true) 
+0

感謝您的答案。看起來像它正在工作。但是,我得到以下問題:scala> val row2 = src.map(x => x.split(「,」))。map(x => Row(x(0),BigDecimal.decimal(x(1 )。toDouble))) :34:error:值decimal不是對象的成員scala.math.BigDecimal val row2 = src.map(x => x.split(「,」))。map(x =>行(X(0),BigDecimal.decimal(X(1).toDouble)))。所以我試過了:val row2 = src.map(x => x.split(「,」))。map(x => Row(x(0),BigDecimal(x(1).toDouble)))and我能夠得到結果。爲什麼第一個值顯示爲「0E-10」而不是0的任何原因。 –

+0

1. BigDecimal()等同於BigDecimal.decimal()。 – cstur4

+0

2.顯示爲「0E-10」,因此類型爲十進制。 'BigDecimal(0)'print'0',但是'BigDecimal(0:Double)'應該打印'0.0'。 – cstur4

0

解決您的問題的一種更簡單的方法是直接將csv文件作爲數據框加載。你可以是這樣做的:

val df = sqlContext.read.format("com.databricks.spark.csv") 
    .option("header", "false") // no header 
    .option("inferSchema", "true") 
    .load("/file/path/") 

或爲星火>2.0

val spark = SparkSession.builder.getOrCreate() 
val df = spark.read 
    .format("com.databricks.spark.csv") 
    .option("header", "false") // no headers 
    .load("/file/path") 

輸出:

df.show() 

+-----+--------------+ 
| _c0|   _c1| 
+-----+--------------+ 
|test1|    0| 
|test2|   0.67| 
|test3|   10.65| 
|test4|-10.1234567890| 
+-----+--------------+ 
1

當你讀一個文件作爲sc.textFile它讀取所有的值string ,所以錯誤是由於在創建時應用schemadataframe

爲此,您可以在第二值轉換爲Decimal應用schema

val row = src.map(x=>x.split(",")).map(x=>Row(x(0), BigDecimal.decimal(x(1).toDouble))) 

之前,或者,如果你讀CAV文件,那麼你可以使用spark-csv讀取csv文件和讀取文件時提供的模式。

val df = sqlContext.read 
    .format("com.databricks.spark.csv") 
    .option("header", "true") // Use first line of all files as header 
    .option("inferSchema", "true") // Automatically infer data types 
    .load("cars.csv") 

火花> 2.0

spark.read 
     .option("header", true) 
     .schema(sch) 
     .csv(file) 

希望這有助於!

+0

第一種方法不起作用,至少不在Spark 1.6上。 – philantrovert

+0

你的建議與cstur4建議的一樣。你們兩個都是對的。請讓我知道,如果你知道爲什麼0在上面提供的答案中顯示爲0E-10。 –