Je veux créer sur DataFrame
avec un schéma spécifié dans Scala. J'ai essayé d'utiliser JSON read (je veux dire lire un fichier vide) mais je ne pense pas que ce soit la meilleure pratique.
Supposons que vous souhaitiez un cadre de données avec le schéma suivant:
root
|-- k: string (nullable = true)
|-- v: integer (nullable = false)
Vous définissez simplement le schéma pour un cadre de données et utilisez vide RDD[Row]
:
import org.Apache.spark.sql.types.{
StructType, StructField, StringType, IntegerType}
import org.Apache.spark.sql.Row
val schema = StructType(
StructField("k", StringType, true) ::
StructField("v", IntegerType, false) :: Nil)
// Spark < 2.0
// sqlContext.createDataFrame(sc.emptyRDD[Row], schema)
spark.createDataFrame(sc.emptyRDD[Row], schema)
L'équivalent PySpark est presque identique:
from pyspark.sql.types import StructType, StructField, IntegerType, StringType
schema = StructType([
StructField("k", StringType(), True), StructField("v", IntegerType(), False)
])
# or df = sc.parallelize([]).toDF(schema)
# Spark < 2.0
# sqlContext.createDataFrame([], schema)
df = spark.createDataFrame([], schema)
Utilisation de codeurs implicites (Scala uniquement) avec Product
types comme Tuple
:
import spark.implicits._
Seq.empty[(String, Int)].toDF("k", "v")
ou classe de cas:
case class KV(k: String, v: Int)
Seq.empty[KV].toDF
ou
spark.emptyDataset[KV].toDF
À partir de Spark 2.0.0, vous pouvez procéder comme suit.
Définissons une classe de cas Person
:
scala> case class Person(id: Int, name: String)
defined class Person
Importer spark
SparkSession implicite Encoders
:
scala> import spark.implicits._
import spark.implicits._
Et utilisez SparkSession pour créer un Dataset[Person]
vide:
scala> spark.emptyDataset[Person]
res0: org.Apache.spark.sql.Dataset[Person] = [id: int, name: string]
Vous pouvez également utiliser un schéma "DSL" (voir Fonctions de support pour les DataFrames dans org.Apache.spark.sql.ColumnName ).
scala> val id = $"id".int
id: org.Apache.spark.sql.types.StructField = StructField(id,IntegerType,true)
scala> val name = $"name".string
name: org.Apache.spark.sql.types.StructField = StructField(name,StringType,true)
scala> import org.Apache.spark.sql.types.StructType
import org.Apache.spark.sql.types.StructType
scala> val mySchema = StructType(id :: name :: Nil)
mySchema: org.Apache.spark.sql.types.StructType = StructType(StructField(id,IntegerType,true), StructField(name,StringType,true))
scala> import org.Apache.spark.sql.Row
import org.Apache.spark.sql.Row
scala> val emptyDF = spark.createDataFrame(sc.emptyRDD[Row], mySchema)
emptyDF: org.Apache.spark.sql.DataFrame = [id: int, name: string]
scala> emptyDF.printSchema
root
|-- id: integer (nullable = true)
|-- name: string (nullable = true)
import scala.reflect.runtime.{universe => ru}
def createEmptyDataFrame[T: ru.TypeTag] =
hiveContext.createDataFrame(sc.emptyRDD[Row],
ScalaReflection.schemaFor(ru.typeTag[T].tpe).dataType.asInstanceOf[StructType]
)
case class RawData(id: String, firstname: String, lastname: String, age: Int)
val sourceDF = createEmptyDataFrame[RawData]
Ici, vous pouvez créer un schéma en utilisant StructType dans scala et transmettre le RDD vide afin que vous puissiez créer une table vide. Le code suivant est pour le même.
import org.Apache.spark.SparkConf
import org.Apache.spark.SparkContext
import org.Apache.spark.sql._
import org.Apache.spark.sql.Row
import org.Apache.spark.sql.SparkSession
import org.Apache.spark.sql.types.StructType
import org.Apache.spark.sql.types.StructField
import org.Apache.spark.sql.types.IntegerType
import org.Apache.spark.sql.types.BooleanType
import org.Apache.spark.sql.types.LongType
import org.Apache.spark.sql.types.StringType
//import org.Apache.hadoop.Hive.serde2.objectinspector.StructField
object EmptyTable extends App {
val conf = new SparkConf;
val sc = new SparkContext(conf)
//create sparksession object
val sparkSession = SparkSession.builder().enableHiveSupport().getOrCreate()
//Created schema for three columns
val schema = StructType(
StructField("Emp_ID", LongType, true) ::
StructField("Emp_Name", StringType, false) ::
StructField("Emp_Salary", LongType, false) :: Nil)
//Created Empty RDD
var dataRDD = sc.emptyRDD[Row]
//pass rdd and schema to create dataframe
val newDFSchema = sparkSession.createDataFrame(dataRDD, schema)
newDFSchema.createOrReplaceTempView("tempSchema")
sparkSession.sql("create table Finaltable AS select * from tempSchema")
}
À partir de Spark 2.4.3
val df = SparkSession.builder().getOrCreate().emptyDataFrame
Voici une solution qui crée une image vide dans pyspark 2.0.0 ou plus.
from pyspark.sql import SQLContext
sc = spark.sparkContext
schema = StructType([StructField('col1', StringType(),False),StructField('col2', IntegerType(), True)])
sqlContext.createDataFrame(sc.emptyRDD(), schema)
Version Java pour créer un DataSet vide:
public Dataset<Row> emptyDataSet(){
SparkSession spark = SparkSession.builder().appName("Simple Application")
.config("spark.master", "local").getOrCreate();
Dataset<Row> emptyDataSet = spark.createDataFrame(new ArrayList<>(), getSchema());
return emptyDataSet;
}
public StructType getSchema() {
String schemaString = “column1 column2 column3 column4 column5”;
List<StructField> fields = new ArrayList<>();
StructField indexField = DataTypes.createStructField(“column0”, DataTypes.LongType, true);
fields.add(indexField);
for (String fieldName : schemaString.split(" ")) {
StructField field = DataTypes.createStructField(fieldName, DataTypes.StringType, true);
fields.add(field);
}
StructType schema = DataTypes.createStructType(fields);
return schema;
}