web-dev-qa-db-ja.com

Spark 2.X Datasetsでカスタムエンコーダーを作成するには?

Sparkデータセットは、Pojo /プリミティブの行からEncoderに移動します。 Catalystエンジンは、ExpressionEncoderを使用してSQL式の列を変換します。ただし、独自の実装のテンプレートとして使用できるEncoderの他のサブクラスは存在しないようです。

以下は、Spark 1.X /新しい体制でコンパイルされないDataFramesで満足のいくコードの例です。

//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[Byte@unchecked] => arr
      case _ => {
        log.error("Unsupport value type")
        null
      }
    }
    (id, label, channels, height, width, data)
  }).persist(StorageLevel.DISK_ONLY)

}

コンパイラエラーが発生します

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 => {
          ^

だから何とか/どこかにする手段があるはずです

  • カスタムエンコーダーを定義/実装する
  • DataFrame(現在はRow型のデータセット)でマッピングを実行するときに適用します
  • 他のカスタムコードで使用するエンコーダーを登録する

これらの手順を正常に実行するコードを探しています。

18
javadba

私が知る限り、1.6以降で実際に何も変更されておらず、 データセットにカスタムオブジェクトを保存する方法 で説明されているソリューションのみが利用可能なオプションです。それでも、現在のコードは、製品タイプのデフォルトのエンコーダーで問題なく動作するはずです。

コードが1.xで機能し、2.0.0で機能しない理由を理解するには、署名を確認する必要があります。 1.x DataFrame.mapは、関数Row => Tおよび変換RDD[Row] into RDD[T]

2.0.0でDataFrame.mapは、タイプRow => Tも同様ですが、変換Dataset[Row](別名DataFrame)からDataset[T]したがってTにはEncoderが必要です。 「古い」動作を取得したい場合は、RDDを明示的に使用する必要があります。

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

にとって Dataset[Row]map参照 データフレームの行を更新された行にマッピングしようとしているときにエンコーダーのエラー

18
zero323

暗黙のエンコーダーをインポートしましたか?

インポートspark.implicits._

http://spark.Apache.org/docs/2.0.0-preview/api/scala/index.html#org.Apache.spark.sql.Encoder

3
eyal edelman

Spark.implicits._をインポートしました。sparkはSparkSessionであり、エラーを解決し、カスタムエンコーダーがインポートされました。

また、カスタムエンコーダーの作成は、試したことがない方法です。

実用的なソリューション:-SparkSessionを作成し、以下をインポートします

インポートspark.implicits._

0
Valan Aravind