J'ai une structure RDD
RDD[(String, String)]
et je veux créer 2 listes (une pour chaque dimension du rdd).
J'ai essayé d'utiliser le rdd.foreach () et de remplir deux ListBuffers, puis de les convertir en listes, mais je suppose que chaque nœud crée son propre ListBuffer car après l'itération, les BufferLists sont vides. Comment puis-je le faire ?
EDIT: ma démarche
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)
et le résultat est:
rdd: 31990654
bufferList: 0
list: 0
Si vous voulez vraiment en créer deux Lists - ce qui signifie, vous voulez que toutes les données distribuées soient collectées dans l'application du pilote (risquant la lenteur ou OutOfMemoryError
) - vous pouvez utiliser collect
puis utilisez des opérations simples map
sur le résultat:
val list: List[(String, String)] = rdd.collect().toList
val col1: List[String] = list.map(_._1)
val col2: List[String] = list.map(_._2)
Alternativement - si vous voulez "diviser" votre RDD en deux RDD - c'est assez similaire sans collecter les données:
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)
Une troisième alternative consiste à mapper d'abord sur ces deux RDD, puis à collecter chacun d'eux, mais ce n'est pas très différent de la première option et souffre des mêmes risques et limites.
Comme alternative à la réponse de Tzach Zohar, vous pouvez utiliser unzip
dans les listes:
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)
Ou keys
et values
sur les RDD
s:
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