web-dev-qa-db-fra.com

Conversion de RDD en Dataframe dans Spark/Scala

Le RDD a été créé au format Array[Array[String]] et a les valeurs suivantes:

 Array[Array[String]] = Array(Array(4580056797, 0, 2015-07-29 10:38:42, 0, 1, 1), Array(4580056797, 0, 2015-07-29 10:38:42, 0, 1, 1), Array(4580056797, 0, 2015-07-29 10:38:42, 0, 1, 1), Array(4580057445, 0, 2015-07-29 10:40:37, 0, 1, 1), Array(4580057445, 0, 2015-07-29 10:40:37, 0, 1, 1))

Je veux créer un dataFrame avec le schéma: 

val schemaString = "callId oCallId callTime duration calltype swId"

Prochaines étapes:

scala> val rowRDD = rdd.map(p => Array(p(0), p(1), p(2),p(3),p(4),p(5).trim))
rowRDD: org.Apache.spark.rdd.RDD[Array[String]] = MapPartitionsRDD[14] at map at <console>:39
scala> val calDF = sqlContext.createDataFrame(rowRDD, schema)

Donne l'erreur suivante:

console: 45: erreur: valeur de méthode surchargée createDataFrame avec alternatives: (rdd: org.Apache.spark.api.Java.JavaRDD [], beanClass: Classe []) org.Apache.spark .sql.DataFrame (rdd: org.Apache.spark.rdd.RDD [], beanClass: Classe []) org.Apache.spark.sql.DataFrame (rowRDD : org.Apache.spark.api.Java.JavaRDD [org.Apache.spark.sql.Row], schéma: org.Apache.spark.sql.types.StructType) org.Apache.spark.sql.DataFrame (rowRDD: org.Apache.spark.rdd.RDD [org.Apache.spark.sql.Row], schéma: org.Apache.spark.sql.types.StructType) org.Apache.spark.sql.DataFrame ne peut pas être appliqué à (org.Apache.spark.rdd.RDD [Array [String]],
org.Apache.spark.sql.types.StructType) val calDF = sqlContext.createDataFrame (rowRDD, schéma)

5
sparkDabbler

Il suffit de coller dans un spark-Shell:

val a = 
  Array(
    Array("4580056797", "0", "2015-07-29 10:38:42", "0", "1", "1"), 
    Array("4580056797", "0", "2015-07-29 10:38:42", "0", "1", "1"))

val rdd = sc.makeRDD(a)

case class X(callId: String, oCallId: String, 
  callTime: String, duration: String, calltype: String, swId: String)

Ensuite, map() sur le RDD pour créer des instances de la classe de cas, puis créez le DataFrame en utilisant toDF():

scala> val df = rdd.map { 
  case Array(s0, s1, s2, s3, s4, s5) => X(s0, s1, s2, s3, s4, s5) }.toDF()
df: org.Apache.spark.sql.DataFrame = 
  [callId: string, oCallId: string, callTime: string, 
    duration: string, calltype: string, swId: string]

Cela déduit le schéma de la classe de cas.

Ensuite, vous pouvez procéder avec:

scala> df.printSchema()
root
 |-- callId: string (nullable = true)
 |-- oCallId: string (nullable = true)
 |-- callTime: string (nullable = true)
 |-- duration: string (nullable = true)
 |-- calltype: string (nullable = true)
 |-- swId: string (nullable = true)

scala> df.show()
+----------+-------+-------------------+--------+--------+----+
|    callId|oCallId|           callTime|duration|calltype|swId|
+----------+-------+-------------------+--------+--------+----+
|4580056797|      0|2015-07-29 10:38:42|       0|       1|   1|
|4580056797|      0|2015-07-29 10:38:42|       0|       1|   1|
+----------+-------+-------------------+--------+--------+----+

Si vous voulez utiliser toDF() dans un programme normal (pas dans le spark-Shell), assurez-vous (entre guillemets de ici ):

  • Pour import sqlContext.implicits._ juste après la création de la SQLContext
  • Définissez la classe de cas en dehors de la méthode en utilisant toDF()
9
Beryllium

Vous devez d'abord convertir Array en Row, puis définir un schéma. J'ai supposé que la plupart de vos champs sont Long 

    val rdd: RDD[Array[String]] = ???
    val rows: RDD[Row] = rdd map {
      case Array(callId, oCallId, callTime, duration, swId) =>
        Row(callId.toLong, oCallId.toLong, callTime, duration.toLong, swId.toLong)
    }

    object schema {
      val callId = StructField("callId", LongType)
      val oCallId = StructField("oCallId", StringType)
      val callTime = StructField("callTime", StringType)
      val duration = StructField("duration", LongType)
      val swId = StructField("swId", LongType)

      val struct = StructType(Array(callId, oCallId, callTime, duration, swId))
    }

    sqlContext.createDataFrame(rows, schema.struct)
4
Eugene Zhulenev

Je suppose que votre schema est, comme dans le Spark Guide , comme suit:

val schema =
  StructType(
    schemaString.split(" ").map(fieldName => StructField(fieldName, StringType, true)))

Si vous regardez la signature de createDataFrame , voici celle qui accepte un StructType comme deuxième argument (pour Scala)

def createDataFrame (rowRDD: RDD [Row], schéma: StructType): DataFrame

Crée un DataFrame à partir d'un RDD contenant des lignes en utilisant le schéma Donné.

Donc, il accepte comme 1er argument un RDD[Row]. Ce que vous avez dans rowRDD est un RDD[Array[String]] donc il y a une discordance.

Avez-vous besoin d'un RDD[Array[String]]?

Sinon, vous pouvez utiliser les éléments suivants pour créer votre cadre de données:

val rowRDD = rdd.map(p => Row(p(0), p(1), p(2),p(3),p(4),p(5).trim))
1
ccheneson