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
型のデータセット)でマッピングを実行するときに適用しますこれらの手順を正常に実行するコードを探しています。
私が知る限り、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
参照 データフレームの行を更新された行にマッピングしようとしているときにエンコーダーのエラー
暗黙のエンコーダーをインポートしましたか?
インポートspark.implicits._
http://spark.Apache.org/docs/2.0.0-preview/api/scala/index.html#org.Apache.spark.sql.Encoder
Spark.implicits._をインポートしました。sparkはSparkSessionであり、エラーを解決し、カスタムエンコーダーがインポートされました。
また、カスタムエンコーダーの作成は、試したことがない方法です。
実用的なソリューション:-SparkSessionを作成し、以下をインポートします
インポートspark.implicits._