Alors que j'essaie de créer une trame de données en utilisant un type décimal, cela me lance l'erreur ci-dessous.

J'effectue les étapes suivantes:

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)

// Création d'un schéma

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 est créé sans aucune erreur, mais lorsque je lance l'action df1.collect (), cela me donne l'erreur ci-dessous:

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

contenu test_file.txt:

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

Y a-t-il un problème avec la façon dont je crée DecimalType?

3
Bharath K 16 août 2017 à 09:47

2 réponses

Meilleure réponse

Vous devez avoir une instance de BigDecimal à convertir en 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()

Le résultat ressemble à ceci:

[test1,0E-10]
[test2,0.6700000000]
[test3,10.6500000000]
[test4,-10.1234567890]
root
 |-- COL1: string (nullable = true)
 |-- COL2: decimal(15,10) (nullable = true)
12
cstur4 16 août 2017 à 07:17

Lorsque vous lisez un fichier comme sc.textFile, il lit toutes les valeurs comme string, une erreur est donc due à l'application de schema lors de la création de dataframe

Pour cela, vous pouvez convertir la deuxième valeur en Decimal avant d'appliquer schema

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

Ou si vous lisez un fichier cav, vous pouvez utiliser spark-csv pour lire le fichier csv et fournir le schéma lors de la lecture du fichier.

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

Pour Spark> 2.0

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

J'espère que cela t'aides!

1
koiralo 16 août 2017 à 07:19