Eu costumo usar a map
função em spark Dataset rows para fazer transformações em Scala em objetos tipados. Meu padrão usual é converter resultados intermediários criados a partir de transformações de dataframe ( withColumn
, groupBy
, etc.) e criar um Dataset tipado do resultado intermediário para que eu possa usar map
.
Isso funciona bem, mas leva a muitas classes de casos "temporárias" para resultados intermediários ou tipos de tuplas difíceis de manejar.
Uma alternativa seria executar map
em um quadro de dados e recuperar campos digitados da linha usando, getAs[T]
mas isso não parece funcionar com spark.implicits
if T
é uma classe de caso.
Por exemplo, isso dá o erroClassCastException: org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema cannot be cast to Person
import org.apache.spark._
import org.apache.spark.sql._
import org.apache.spark.sql.functions.{round => colRound, min => colMin, max => colMax, _}
import org.apache.spark.sql.expressions.Window
import spark.implicits._
final case class Person(name: String, age: Integer)
val people = Seq(Person("Alice", 20), Person("Bob", 30), Person("Charlie", 40)).toDS
val df = people.alias("p")
.select($"p.name", struct($"p.*").alias("person"))
val ds = df.map(row => {
val name = row.getAs[String]("name")
val person = row.getAs[Person]("person")
(name, person)
})
display(ds)
enquanto isso funciona bem:
import org.apache.spark._
import org.apache.spark.sql._
import org.apache.spark.sql.functions.{round => colRound, min => colMin, max => colMax, _}
import org.apache.spark.sql.expressions.Window
import spark.implicits._
final case class Person(name: String, age: Integer)
val people = Seq(Person("Alice", 20), Person("Bob", 30), Person("Charlie", 40)).toDS
val df = people.alias("p")
.select($"p.name", struct($"p.*").alias("person"))
.as[Tuple2[String, Person]]
val ds = df.map(row => {
val name = row._1
val person = row._2
(name, person)
})
display(ds)
Então o spark está convertendo alegremente a estrutura person do dataframe para a Person
classe case no segundo exemplo, mas não fará isso no primeiro exemplo. Alguém sabe uma maneira simples de consertar isso?
Obrigado,
Davi