web-dev-qa-db-ja.com

Spark / ScalaでRDDをDataframeに変換する

RDDはArray[Array[String]]の形式で作成されており、次の値があります。

val rdd : Array[Array[String]] = Array(
Array("4580056797", "0", "2015-07-29 10:38:42", "0", "1", "1"), 
Array("4580056797", "0", "2015-07-29 10:38:43", "0", "1", "1"))

スキーマを使用してdataFrameを作成します。

val schemaString = "callId oCallId callTime duration calltype swId"

次のステップ:

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)

次のエラーが発生します。

console:45: error: overloaded method value createDataFrame with alternatives:
     (rdd: org.Apache.spark.api.Java.JavaRDD[_],beanClass: Class[_])org.Apache.spark.sql.DataFrame <and>
    (rdd: org.Apache.spark.rdd.RDD[_],beanClass: Class[_])org.Apache.spark.sql.DataFrame <and>
    (rowRDD: org.Apache.spark.api.Java.JavaRDD[org.Apache.spark.sql.Row],schema: org.Apache.spark.sql.types.StructType)org.Apache.spark.sql.DataFrame <and>
    (rowRDD: org.Apache.spark.rdd.RDD[org.Apache.spark.sql.Row],schema: org.Apache.spark.sql.types.StructType)org.Apache.spark.sql.DataFrame
    cannot be applied to (org.Apache.spark.rdd.RDD[Array[String]],   
    org.Apache.spark.sql.types.StructType)
       val calDF = sqlContext.createDataFrame(rowRDD, schema)
6
sparkDabbler

_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)
_

次に、RDDでmap()を実行してケースクラスのインスタンスを作成し、次にtoDF()を使用してDataFrameを作成します。

_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]
_

これは、ケースクラスからスキーマを推測します。

次に、続行できます。

_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|
+----------+-------+-------------------+--------+--------+----+
_

(_spark-Shell_ではなく)通常のプログラムでtoDF()を使用する場合は、( here から引用)を確認してください。

  • SQLContextを作成した直後の_import sqlContext.implicits.__へ
  • toDF()を使用して、メソッドの外部でケースクラスを定義します
12
Beryllium

最初にArrayRowに変換してから、スキーマを定義する必要があります。ほとんどのフィールドは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

spark 1.6.1およびscala 2.10の使用

同じエラーが発生しましたerror: overloaded method value createDataFrame with alternatives:

私にとって、getchaはcreateDataFrameの署名でしたが、val rdd : List[Row]を使用しようとしましたが、Java.util.List[org.Apache.spark.sql.Row]scala.collection.immutable.List[org.Apache.spark.sql.Row]が同じではないため、失敗しました。

私が見つけた実用的な解決策は、val rdd : Array[Array[String]]RDD[Row]経由でList[Array[String]]に変換することです。これは documentation にあるものに最も近いと思います

import org.Apache.spark.sql.Row
import org.Apache.spark.sql.types.{StructType,StructField,StringType};
val sqlContext = new org.Apache.spark.sql.SQLContext(sc)

val rdd_original : 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"))

val rdd : List[Array[String]] = rdd_original.toList

val schemaString = "callId oCallId callTime duration calltype swId"

// Generate the schema based on the string of schema
val schema =
  StructType(
    schemaString.split(" ").map(fieldName => StructField(fieldName, StringType, true)))

// Convert records of the RDD to Rows.
val rowRDD = rdd.map(p => Row(p: _*)) // using splat is easier
// val rowRDD = rdd.map(p => Row(p(0), p(1), p(2), p(3), p(4), p(5))) // this also works

val df = sqlContext.createDataFrame(sc.parallelize(rowRDD:List[Row]), schema)
df.show
2
Sida Zhou

私はあなたのschemaSpark Guide のように、次のようであると仮定します:

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

createDataFrame のシグニチャーを見ると、StructTypeを2番目の引数(Scalaの場合)として受け入れるものがここにあります。

def createDataFrame(rowRDD:RDD [Row]、schema:StructType):DataFrame

指定されたスキーマを使用して、行を含むRDDからDataFrameを作成します。

したがって、最初の引数としてRDD[Row]を受け入れます。 rowRDDにあるのはRDD[Array[String]]なので、不一致があります。

RDD[Array[String]]が必要ですか?

それ以外の場合は、次を使用してデータフレームを作成できます。

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