Bagaimana cara membuat DataFrame kosong dengan skema tertentu?

94

Saya ingin membuat DataFramedengan skema tertentu di Scala. Saya telah mencoba menggunakan JSON read (maksud saya membaca file kosong) tetapi menurut saya itu bukan praktik terbaik.

pengguna1735076
sumber

Jawaban:

126

Mari kita asumsikan Anda menginginkan bingkai data dengan skema berikut:

root
 |-- k: string (nullable = true)
 |-- v: integer (nullable = false)

Anda cukup menentukan skema untuk bingkai data dan menggunakan kosong 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)

Setara PySpark hampir identik:

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)

Menggunakan encoder implisit (hanya Scala) dengan Producttipe seperti Tuple:

import spark.implicits._

Seq.empty[(String, Int)].toDF("k", "v")

atau kelas kasus:

case class KV(k: String, v: Int)

Seq.empty[KV].toDF

atau

spark.emptyDataset[KV].toDF
nol323
sumber
Ini adalah jawaban yang paling tepat - lengkap, dan juga berguna jika Anda ingin mereproduksi skema kumpulan data yang ada dengan cepat. Saya tidak tahu mengapa itu bukan yang diterima.
Lucas Lima
40

Mulai Spark 2.0.0, Anda dapat melakukan hal berikut.

Kelas Kasus

Mari tentukan Personkelas kasus:

scala> case class Person(id: Int, name: String)
defined class Person

Impor sparkSparkSession implisit Encoders:

scala> import spark.implicits._
import spark.implicits._

Dan gunakan SparkSession untuk membuat kosong Dataset[Person]:

scala> spark.emptyDataset[Person]
res0: org.apache.spark.sql.Dataset[Person] = [id: int, name: string]

Skema DSL

Anda juga dapat menggunakan Skema "DSL" (lihat Fungsi dukungan untuk DataFrames di 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)
Jacek Laskowski
sumber
Hai, penyusun mengatakan bahwa spark.emptyDatasetmodul saya tidak ada, Bagaimana cara menggunakannya? ada beberapa (benar) mirip dengan (tidak benar) val df = apache.spark.emptyDataset[RawData]?
Peter Krauss
@PeterKrauss sparkadalah nilai yang Anda buat menggunakan SparkSession.builderbukan bagian dari org.apache.sparkpaket. Ada dua sparknama yang digunakan. Ini adalah sparkAnda telah tersedia di spark-shellluar kotak.
Jacek Laskowski
1
Terima kasih Jacek. Saya mengoreksi: objek SparkSession.builder diteruskan sebagai parameter (tampaknya solusi terbaik) dari inisialisasi umum pertama, sekarang sedang berjalan.
Peter Krauss
3
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]
Ravindra
sumber
3

Di sini Anda dapat membuat skema menggunakan StructType dalam skala dan meneruskan Empty RDD sehingga Anda dapat membuat tabel kosong. Kode berikut untuk hal yang sama.

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

}
Nilesh Shinde
sumber
2

Versi Java untuk membuat DataSet kosong:

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;
}
Molay
sumber
1

Berikut adalah solusi yang membuat dataframe kosong di pyspark 2.0.0 atau lebih.

from pyspark.sql import SQLContext
sc = spark.sparkContext
schema = StructType([StructField('col1', StringType(),False),StructField('col2', IntegerType(), True)])
sqlContext.createDataFrame(sc.emptyRDD(), schema)
braj
sumber
1

Ini berguna untuk tujuan pengujian.

Seq.empty[String].toDF()
ss301
sumber
-3

Pada Spark 2.4.3

val df = SparkSession.builder().getOrCreate().emptyDataFrame
hantu rubah
sumber
7
Ini tidak menyelesaikan bagian skema dari pertanyaan.
Andrew Sklyarevsky