Як створити порожній DataFrame із зазначеною схемою?


94

Я хочу створити на DataFrameз вказаною схемою в Scala. Я намагався використовувати JSON read (я маю на увазі читання порожнього файлу), але я не думаю, що це найкраща практика.

Відповіді:


126

Припустимо, вам потрібен кадр даних із такою схемою:

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

Це найбільш відповідна відповідь - повна, а також корисна, якщо ви хочете швидко відтворити схему існуючого набору даних. Не знаю, чому це не прийнято.
Лукас Ліма,

40

Станом на 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]

Схема DSL

Крім того, можна використовувати схему «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]?
Пітер Краус

@PeterKrauss spark- це значення, яке ви створюєте, SparkSession.builderне входячи в org.apache.sparkпакет. Використовуються дві sparkназви. Це те, що у sparkвас є в наявності spark-shellз коробки.
Яцек

1
Дякую Яцеку. Я виправив: об'єкт SparkSession.builder передано як параметр (здається найкращим рішенням) від першої загальної ініціалізації, зараз він запущений.
Пітер Краус

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 в масштабі та передати порожній 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 для створення порожнього набору даних:

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

Ось рішення, яке створює порожній фрейм даних у 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)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.