จะสร้าง DataFrame ที่ว่างเปล่าด้วยสคีมาที่ระบุได้อย่างไร?


100

ฉันต้องการสร้างDataFrameด้วยสคีมาที่ระบุใน Scala ฉันได้พยายามใช้การอ่าน JSON (ฉันหมายถึงการอ่านไฟล์เปล่า) แต่ฉันไม่คิดว่านั่นเป็นแนวทางปฏิบัติที่ดีที่สุด

คำตอบ:


131

สมมติว่าคุณต้องการ data frame ที่มี schema ต่อไปนี้:

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

คุณเพียงกำหนดสคีมาสำหรับกรอบข้อมูลและใช้ช่องว่าง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)

เทียบเท่ากับ PySpark เกือบจะเหมือนกัน:

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)

การใช้ตัวเข้ารหัสโดยนัย (เฉพาะ Scala) กับProductประเภทต่างๆเช่นTuple:

import spark.implicits._

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

หรือชั้นกรณี:

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

Seq.empty[KV].toDF

หรือ

spark.emptyDataset[KV].toDF

นี่เป็นคำตอบที่เหมาะสมที่สุด - สมบูรณ์และยังมีประโยชน์หากคุณต้องการสร้างสคีมาของชุดข้อมูลที่มีอยู่ใหม่อย่างรวดเร็ว ฉันไม่รู้ว่าทำไมถึงไม่เป็นที่ยอมรับ
Lucas Lima

วิธีสร้าง df ด้วย trait แทน case class: stackoverflow.com/questions/64276952/…
supernatural

42

สำหรับ Spark 2.0.0 คุณสามารถทำสิ่งต่อไปนี้ได้

คลาสเคส

มากำหนดPersonคลาสเคส:

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

นำเข้าsparkSparkSession โดยนัยEncoders:

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

และใช้ SparkSession เพื่อสร้างว่างDataset[Person]:

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

Schema DSL

คุณยังสามารถใช้ Schema "DSL" (ดูฟังก์ชันการสนับสนุนสำหรับ DataFramesใน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)

สวัสดีคอมไพเลอร์แจ้งว่าspark.emptyDatasetไม่มีอยู่ในโมดูลของฉันจะใช้อย่างไร มีบางส่วน (ถูกต้อง) คล้ายกับ (ไม่ถูกต้อง) val df = apache.spark.emptyDataset[RawData]?
Peter Krauss

@PeterKrauss sparkคือค่าที่คุณสร้างขึ้นโดยSparkSession.builderไม่ได้เป็นส่วนหนึ่งของorg.apache.sparkแพ็คเกจ มีสองsparkชื่อที่ใช้งาน เป็นของที่sparkคุณมีอยู่ในspark-shellกล่อง
Jacek Laskowski

1
ขอบคุณ Jacek ฉันแก้ไข: วัตถุ SparkSession.builder ถูกส่งผ่านเป็นพารามิเตอร์ (ดูเหมือนจะเป็นทางออกที่ดีที่สุด) จากการเริ่มต้นทั่วไปครั้งแรกตอนนี้กำลังทำงานอยู่
Peter Krauss

มีวิธีสร้าง dataframe เปล่าโดยใช้ trait แทน case class ไหม: stackoverflow.com/questions/64276952/…
supernatural

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]

3

ที่นี่คุณสามารถสร้างสคีมาโดยใช้ StructType ในสกาล่าและส่งผ่าน Empty RDD เพื่อให้คุณสามารถสร้างตารางว่างได้ รหัสต่อไปนี้เป็นรหัสเดียวกัน

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

}

2

เวอร์ชัน Java เพื่อสร้าง DataSet ว่าง:

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;
}

1

นี่คือโซลูชันที่สร้าง dataframe ว่างใน pyspark 2.0.0 ขึ้นไป

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


0

ฉันมีข้อกำหนดพิเศษที่ฉันมี dataframe อยู่แล้ว แต่มีเงื่อนไขบางอย่างฉันต้องส่งคืนดาต้าเฟรมว่างเปล่าดังนั้นฉันจึงส่งคืนdf.limit(0)แทน


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.