私はRDD構造を持っています
RDD[(String, String)]
また、2つのリスト(rddの各次元に1つ)を作成します。
Rdd.foreach()を使用して2つのListBufferを埋めてからリストに変換しようとしましたが、反復後にBufferListsが空になるため、各ノードが独自のListBufferを作成すると思います。どうすればいいですか?
編集:私のアプローチ
val labeled = data_labeled.map { line =>
val parts = line.split(',')
(parts(5), parts(7))
}.cache()
var testList : ListBuffer[String] = new ListBuffer()
labeled.foreach(line =>
testList += line._1
)
val labeledList = testList.toList
println("rdd: " + labeled.count)
println("bufferList: " + testList.size)
println("list: " + labeledList.size)
結果は次のとおりです。
rdd: 31990654
bufferList: 0
list: 0
本当に2つのLists-を作成したい場合は、すべての分散データをドライバーアプリケーションに収集する必要があります(遅延またはOutOfMemoryError
のリスク)-collect
そして、結果に対して単純なmap
操作を使用します。
val list: List[(String, String)] = rdd.collect().toList
val col1: List[String] = list.map(_._1)
val col2: List[String] = list.map(_._2)
または、RDDを2つに「分割」したい場合RDDs-データを収集せずにかなり似ています:
rdd.cache() // to make sure calculation of rdd is not repeated twice
val rdd1: RDD[String] = rdd.map(_._1)
val rdd2: RDD[String] = rdd.map(_._2)
3番目の選択肢は、最初にこれら2つのRDDにマッピングしてから、それぞれを収集することですが、最初のオプションと大差はなく、同じリスクと制限に悩まされます。
Tzach Zoharの答えの代替として、リストでunzip
を使用できます。
scala> val myRDD = sc.parallelize(Seq(("a", "b"), ("c", "d")))
myRDD: org.Apache.spark.rdd.RDD[(String, String)] = ParallelCollectionRDD[0] at parallelize at <console>:27
scala> val (l1, l2) = myRDD.collect.toList.unzip
l1: List[String] = List(a, c)
l2: List[String] = List(b, d)
または、keys
sのvalues
およびRDD
:
scala> val (rdd1, rdd2) = (myRDD.keys, myRDD.values)
rdd1: org.Apache.spark.rdd.RDD[String] = MapPartitionsRDD[1] at keys at <console>:33
rdd2: org.Apache.spark.rdd.RDD[String] = MapPartitionsRDD[2] at values at <console>:33
scala> rdd1.foreach{println}
a
c
scala> rdd2.foreach{println}
d
b