L'exemple de code suivant essaie de placer certains objets de cas dans une trame de données. Le code inclut la définition d'une hiérarchie d'objets de cas et une classe de cas utilisant ce trait:
import org.Apache.spark.{SparkContext, SparkConf}
import org.Apache.spark.sql.SQLContext
sealed trait Some
case object AType extends Some
case object BType extends Some
case class Data( name : String, t: Some)
object Example {
def main(args: Array[String]) : Unit = {
val conf = new SparkConf()
.setAppName( "Example" )
.setMaster( "local[*]")
val sc = new SparkContext(conf)
val sqlContext = new SQLContext(sc)
import sqlContext.implicits._
val df = sc.parallelize( Seq( Data( "a", AType), Data( "b", BType) ), 4).toDF()
df.show()
}
}
Lors de l'exécution du code, je rencontre malheureusement l'exception suivante:
Java.lang.UnsupportedOperationException: Schema for type Some is not supported
Some
)?Enumeration
directement, mais aussi sans succès. (voir ci-dessous)Code pour Enumeration
:
object Some extends Enumeration {
type Some = Value
val AType, BType = Value
}
Merci d'avance. J'espère que la meilleure approche n'est pas d'utiliser des chaînes à la place.
Spark 2.0.0 + :
UserDefinedType
a été rendu privé dans Spark 2.0.0 et pour l'instant il n'a pas de remplacement convivial Dataset
.
Voir: SPARK-14155 (Masquer UserDefinedType dans Spark 2.0)
La plupart du temps, le typage statique Dataset
peut servir de remplacement. Il y a un Jira en attente SPARK-7768 pour rendre à nouveau l'API UDT publique avec la version cible 2.4.
Voir aussi Comment stocker des objets personnalisés dans un ensemble de données?
Spark <2.0.0
Existe-t-il une possibilité d'ajouter ou de définir un schéma pour certains types (ici tapez Some)?
Je suppose que la réponse dépend à quel point vous en avez besoin. Il semble qu'il soit possible de créer un UserDefinedType
mais il nécessite un accès à DeveloperApi
et n'est pas exactement simple ou bien documenté.
import org.Apache.spark.sql.types._
@SQLUserDefinedType(udt = classOf[SomeUDT])
sealed trait Some
case object AType extends Some
case object BType extends Some
class SomeUDT extends UserDefinedType[Some] {
override def sqlType: DataType = IntegerType
override def serialize(obj: Any) = {
obj match {
case AType => 0
case BType => 1
}
}
override def deserialize(datum: Any): Some = {
datum match {
case 0 => AType
case 1 => BType
}
}
override def userClass: Class[Some] = classOf[Some]
}
Vous devriez probablement remplacer également hashCode
et equals
.
Son homologue PySpark peut ressembler à ceci:
from enum import Enum, unique
from pyspark.sql.types import UserDefinedType, IntegerType
class SomeUDT(UserDefinedType):
@classmethod
def sqlType(self):
return IntegerType()
@classmethod
def module(cls):
return cls.__module__
@classmethod
def scalaUDT(cls): # Required in Spark < 1.5
return 'net.zero323.enum.SomeUDT'
def serialize(self, obj):
return obj.value
def deserialize(self, datum):
return {x.value: x for x in Some}[datum]
@unique
class Some(Enum):
__UDT__ = SomeUDT()
AType = 0
BType = 1
Dans Spark <1.5 Python UDT nécessite une paire Scala UDT, mais il semble que ce ne soit plus le cas dans 1.5.
Pour un UDT simple comme vous pouvez utiliser des types simples (par exemple IntegerType
au lieu de l'ensemble Struct
).