Làm cách nào để tạo một DataFrame trống với một lược đồ được chỉ định?


94

Tôi muốn tạo trên DataFramevới một lược đồ được chỉ định trong Scala. Tôi đã cố gắng sử dụng JSON read (ý tôi là đọc tệp trống) nhưng tôi không nghĩ đó là phương pháp hay nhất.

Câu trả lời:


126

Giả sử bạn muốn một khung dữ liệu với lược đồ sau:

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

Bạn chỉ cần xác định lược đồ cho một khung dữ liệu và sử dụng rỗng 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)

Tương đương PySpark gần như giống hệt nhau:

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)

Sử dụng bộ mã hóa ngầm định (chỉ dành cho Scala) với Productcác loại như Tuple:

import spark.implicits._

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

hoặc lớp trường hợp:

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

Seq.empty[KV].toDF

hoặc là

spark.emptyDataset[KV].toDF

Đây là câu trả lời thích hợp nhất - đầy đủ và cũng hữu ích nếu bạn muốn tạo lại lược đồ của một tập dữ liệu hiện có một cách nhanh chóng. Tôi không biết tại sao nó không phải là cái được chấp nhận.
Lucas Lima

40

Đối với Spark 2.0.0, bạn có thể làm như sau.

Lớp vỏ

Hãy xác định một Personlớp trường hợp:

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

Nhập sparkSparkSession ngầm Encoders:

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

Và sử dụng SparkSession để tạo trống Dataset[Person]:

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

Sơ đồ DSL

Bạn cũng có thể sử dụng lược đồ "DSL" (xem Các chức năng hỗ trợ cho DataFrames trong 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)

Xin chào, trình biên dịch nói rằng spark.emptyDatasetkhông tồn tại trên mô-đun của tôi, Làm thế nào để sử dụng nó? có một số (đúng) tương tự với (không đúng) val df = apache.spark.emptyDataset[RawData]?
Peter Krauss

@PeterKrauss sparklà giá trị bạn tạo SparkSession.builderkhông phải là một phần của org.apache.sparkgói. Có hai sparktên đang được sử dụng. Đó là thứ sparkbạn có sẵn trong spark-shellhộp.
Jacek Laskowski

1
Cảm ơn Jacek. Tôi đã sửa: đối tượng SparkSession.builder được truyền dưới dạng tham số (có vẻ là giải pháp tốt nhất) từ lần khởi tạo chung đầu tiên, hiện đang chạy.
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]

3

Tại đây, bạn có thể tạo lược đồ bằng cách sử dụng StructType trong scala và chuyển RDD trống để bạn có thể tạo bảng trống. Mã sau là tương tự.

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

Phiên bản Java để tạo DataSet trống:

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

Đây là giải pháp tạo khung dữ liệu trống trong pyspark 2.0.0 trở lên.

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

1

Điều này rất hữu ích cho mục đích thử nghiệm.

Seq.empty[String].toDF()

-3

Kể từ Spark 2.4.3

val df = SparkSession.builder().getOrCreate().emptyDataFrame

7
Điều này không giải quyết phần lược đồ của câu hỏi.
Andrew Sklyarevsky
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.