2017-08-16 36 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。 –