Je charge un fichier CSV dans un DataFrame comme ci-dessous.
val conf=new SparkConf().setAppName("dataframes").setMaster("local")
val sc=new SparkContext(conf)
val spark=SparkSession.builder().getOrCreate()
import spark.implicits._
val df = spark.
read.
format("org.Apache.spark.csv").
option("header", true).
csv("/home/cloudera/Book1.csv")
scala> df.printSchema()
root
|-- name: string (nullable = true)
|-- address: string (nullable = true)
|-- age: string (nullable = true)
Comment changer la colonne age
pour qu'elle soit de type Int
?
Il y a inferSchema
option pour reconnaître automatiquement le type de la variable par:
val df=spark.read
.format("org.Apache.spark.csv")
.option("header", true)
.option("inferSchema", true) // <-- HERE
.csv("/home/cloudera/Book1.csv")
spark-csv
était à l'origine une bibliothèque externe de databricks, mais incluse dans le noyau spark from spark version 2.0 onwards. You can refer to documentation on the library's page github pour trouver les options disponibles.
Étant donné val spark=SparkSession.builder().getOrCreate()
I devinez vous utilisez Spark 2.x.
Tout d'abord, veuillez noter que Spark 2.x a un support natif pour le format CSV et en tant que tel ne nécessite pas de spécifier le format par son nom long, c'est-à-dire org.Apache.spark.csv
, Mais juste csv
.
spark.read.format("csv")...
Puisque vous utilisez l'opérateur csv
, le format CSV est implicite et vous pouvez donc ignorer/supprimer format("csv")
.
// note that I removed format("csv")
spark.read.option("header", true).csv("/home/cloudera/Book1.csv")
Avec cela, vous avez beaucoup d'options, mais je recommande fortement d'utiliser une classe de cas pour ... juste le schéma. Voir la dernière solution si vous êtes curieux de savoir comment le faire dans Spark 2.0.
Vous pouvez utiliser l'opérateur cast .
scala> Seq("1").toDF("str").withColumn("num", 'str cast "int").printSchema
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
Vous pouvez également utiliser votre propre schéma artisanal avec StructType et StructField comme suit:
import org.Apache.spark.sql.types._
val schema = StructType(
StructField("str", StringType, true) ::
StructField("num", IntegerType, true) :: Nil)
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
val q = spark.
read.
option("header", true).
schema(schema).
csv("numbers.csv")
scala> q.printSchema
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
Ce que j'ai trouvé assez intéressant récemment était ce qu'on appelle Schéma DSL . Le schéma ci-dessus construit à l'aide de StructType
et StructField
peut être réécrit comme suit:
import org.Apache.spark.sql.types._
val schema = StructType(
$"str".string ::
$"num".int :: Nil)
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
// or even
val schema = new StructType().
add($"str".string).
add($"num".int)
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = true)
Les encodeurs sont si faciles à utiliser qu'il est difficile de croire que vous ne pouvez pas les vouloir, ne serait-ce que pour construire un schéma sans traiter avec StructType
, StructField
et DataType
.
// Define a business object that describes your dataset
case class MyRecord(str: String, num: Int)
// Use Encoders object to create a schema off the business object
import org.Apache.spark.sql.Encoders
val schema = Encoders.product[MyRecord].schema
scala> schema.printTreeString
root
|-- str: string (nullable = true)
|-- num: integer (nullable = false)