2016-06-08 5 views
14

Spark Datasets bewegen sich von Row zu Encoder für Pojos/Primitive. Die Catalyst-Engine verwendet ExpressionEncoder, um Spalten in einem SQL-Ausdruck zu konvertieren. Es scheint jedoch keine anderen Unterklassen von Encoder zu geben, die als Vorlage für unsere eigenen Implementierungen verwendet werden können. HierWie erstelle ich einen benutzerdefinierten Encoder in Spark 2.X Datasets?

ist ein Beispiel-Code, der in Spark-1.X glücklich ist/Datenrahmen, die nicht in dem neuen Regime nicht kompiliert:

//mapping each row to RDD tuple 
df.map(row => { 
    var id: String = if (!has_id) "" else row.getAs[String]("id") 
    var label: String = row.getAs[String]("label") 
    val channels : Int = if (!has_channels) 0 else row.getAs[Int]("channels") 
    val height : Int = if (!has_height) 0 else row.getAs[Int]("height") 
    val width : Int = if (!has_width) 0 else row.getAs[Int]("width") 
    val data : Array[Byte] = row.getAs[Any]("data") match { 
     case str: String => str.getBytes 
     case arr: Array[[email protected]] => arr 
     case _ => { 
     log.error("Unsupport value type") 
     null 
     } 
    } 
    (id, label, channels, height, width, data) 
    }).persist(StorageLevel.DISK_ONLY) 

}

Wir bekommen einen Compiler-Fehler von

Error:(56, 11) Unable to find encoder for type stored in a Dataset. 
Primitive types (Int, String, etc) and Product types (case classes) are supported 
by importing spark.implicits._ Support for serializing other types will be added in future releases. 
    df.map(row => { 
     ^

Also irgendwie/irgendwo sollte es ein Mittel, um

    sein
  • definieren/implementieren unsere eigene Encoder
  • es Nehmen, wenn eine Abbildung auf der DataFrame Durchführung (das jetzt ein Datensatz vom Typ)
  • für den Encoder-Register von anderen benutzerdefinierten Code

Ich bin Suchen nach Code, der diese Schritte erfolgreich ausführt.

+0

Mögliche Duplikat von [Wie benutzerdefinierte speichern Objekte in einem Datensatz] (http: // Stackoverflow .com/questions/36648128/how-to-store-benutzerdefinierte-Objekte-in-einem-Dataset) – Alec

Antwort

10

Soweit ich seit 1.6 wirklich verändert bewusst nichts bin und die in How to store custom objects in Dataset? beschriebenen Lösungen sind die einzigen verfügbaren Optionen. Nichtsdestotrotz sollte Ihr aktueller Code gut mit Standard-Encodern für Produkttypen funktionieren.

Um einen Einblick zu erhalten, warum Ihr Code in 1.x funktioniert und in 2.0.0 möglicherweise nicht funktioniert, müssen Sie die Signaturen überprüfen. In 1.x ist DataFrame.map eine Methode, die die Funktion Row => T übernimmt und RDD[Row] in RDD[T] transformiert.

In 2.0.0 DataFrame.map nimmt eine Funktion vom Typ Row => T als gut, aber wandelt Dataset[Row] (a.k.a DataFrame) in Dataset[T] daher ein TEncoder erfordert. Wenn Sie die „alte“ Verhalten bekommen möchten, sollten Sie RDD explizit verwenden:

df.rdd.map(row => ???) 

Für Dataset[Row]map siehe Encoder error while trying to map dataframe row to updated row

Verwandte Themen