web-dev-qa-db-ja.com

SparkでデータフレームをMap(Key-Value)に変換する

したがって、Spark=にあるDataFrameは次のようになります。

30列あり、そのうちの一部のみを表示します!

[ABCD,color,NORMAL,N,2015-02-20,1]
[XYZA,color,NORMAL,N,2015-05-04,1]
[GFFD,color,NORMAL,N,2015-07-03,1]
[NAAS,color,NORMAL,N,2015-08-26,1]
[LOWW,color,NORMAL,N,2015-09-26,1]
[KARA,color,NORMAL,N,2015-11-08,1]
[ALEQ,color,NORMAL,N,2015-12-04,1]
[VDDE,size,NORMAL,N,2015-12-23,1]
[QWER,color,NORMAL,N,2016-01-18,1]
[KDSS,color,NORMAL,Y,2015-08-29,1]
[KSDS,color,NORMAL,Y,2015-08-29,1]
[ADSS,color,NORMAL,Y,2015-08-29,1]
[BDSS,runn,NORMAL,Y,2015-08-29,1]
[EDSS,color,NORMAL,Y,2015-08-29,1]

そのため、ScalaでこのdataFrameをキーと値のペアに変換し、キーをDataframeの列の一部として使用し、インデックス0からcount(distinct number)までのキーに一意の値を割り当てる必要があります。

例:上記のケースを使用して、map(key-value)コレクションにScalaのように出力したい:

    ([ABC_color_NORMAL_N_1->0]
    [XYZA_color_NORMAL_N_1->1]
    [GFFD_color_NORMAL_N_1->2]
    [NAAS_color_NORMAL_N_1->3]
    [LOWW_color_NORMAL_N_1->4]
    [KARA_color_NORMAL_N_1->5]
    [ALEQ_color_NORMAL_N_1->6]
    [VDDE_size_NORMAL_N_1->7]
    [QWER_color_NORMAL_N_1->8]
    [KDSS_color_NORMAL_Y_1->9]
    [KSDS_color_NORMAL_Y_1->10]
    [ADSS_color_NORMAL_Y_1->11]
    [BDSS_runn_NORMAL_Y_1->12]
    [EDSS_color_NORMAL_Y_1->13]
    )

私はScala and Sparkと私はこのようなことをしようとしました。

 var map: Map[String, Int] = Map()
    var i = 0
    dataframe.foreach( record =>{
    //Is there a better way of creating a key!
        val key = record(0) + record(1) + record(2) + record(3)
        var index = i
        map += (key -> index)
        i+=1
          }
        )

しかし、これは機能していません。:/これが完了した後、マップはnullです。

9

あなたのコードの主な問題は、modifyworkersで実行されるコード内のドライバー側で作成された変数を試みることです。 Sparkを使用する場合、RDD変換内でドライバー側変数を「読み取り専用」値としてのみ使用できます。

具体的には:

  • マップはドライバーマシンで作成されます
  • マップ(その初期の空の値)はserializedであり、ワーカーノードに送信されます
  • 各ノードがマップを変更する可能性があります(ローカル)
  • foreachが完了すると、結果は破棄されます-結果はnotドライバーに送り返されます。

これを修正するには、変更されたRDD(たとえばmap)を返す変換を選択してキーを作成し、zipWithIndexを使用して実行中の「ids」を追加し、collectAsMapすべてのデータをマップとしてドライバーに戻すには:

val result: Map[String, Long] = dataframe
  .map(record => record(0) + record(1) + record(2) + record(3))
  .zipWithIndex()
  .collectAsMap()

キーの作成自体については、最初の5列を含め、セパレーター(_)それらの間では、次を使用できます。

record => record.toList.take(5).mkString("_")
15
Tzach Zohar