簡體   English   中英

以特定順序合並多個RDD

[英]Merge multiple RDD in a specific order

我試圖將多個RDD字符串以特定順序合並到行的RDD中。 我嘗試創建一個Map[String, RDD[Seq[String]]] (其中Seq僅包含一個元素),然后將它們合並到RDD[Row[String]] ,但這似乎不起作用( RDD[Seq[String]]內容丟失了。)。有人有任何想法嗎?

val t1: StructType
val mapFields: Map[String, RDD[Seq[String]]]
var ordRDD: RDD[Seq[String]] = context.emptyRDD
t1.foreach(field => ordRDD = ordRDD ++ mapFiels(field.name))
val rdd = ordRDD.map(line => Row.fromSeq(line))

編輯:使用zip函數會導致火花異常,因為我的RDD在每個分區中沒有相同數量的元素。 我不知道如何確保每個分區中的元素數均相同,因此我只用index壓縮了它們,然后使用ListMap很好地連接了它們。 也許與mapPartitions函數有關,但是我對Spark API的了解還不夠。

val mapFields: Map[String, RDD[String]]
var ord: ListMap[String, RDD[String]] = ListMap()
t1.foreach(field => ord = ord ++ Map(field.name -> mapFields(field.name)))
// Note : zip = SparkException: Can only zip RDDs with same number of elements in each partition
//val rdd: RDD[Row] = ord.toSeq.map(_._2.map(s => Seq(s))).reduceLeft((rdd1, rdd2) => rdd1.zip(rdd2).map{ case (l1, l2) => l1 ++ l2 }).map(Row.fromSeq)
val zipRdd = ord.toSeq.map(_._2.map(s => Seq(s)).zipWithIndex().map{ case (d, i) => (i, d) })
val concatRdd = zipRdd.reduceLeft((rdd1, rdd2) => rdd1.join(rdd2).map{ case (i, (l1, l2)) => (i, l1 ++ l2)})
val rowRdd: RDD[Row] = concatRdd.map{ case (i, d) => Row.fromSeq(d) }
val df1 = spark.createDataFrame(rowRdd, t1)

此處的關鍵是使用RDD.zip將RDD“壓縮”在一起(創建一個RDD,其中每個記錄都是在ell RDD中具有相同索引的記錄的組合):

import org.apache.spark.sql._
import org.apache.spark.sql.types._

// INPUT: Map does not preserve order (not the defaul implementation, at least) - using Seq
val rdds: Seq[(String, RDD[String])] = Seq(
  "field1" -> sc.parallelize(Seq("a", "b", "c")),
  "field2" -> sc.parallelize(Seq("1", "2", "3")),
  "field3" -> sc.parallelize(Seq("Q", "W", "E"))
)

// Use RDD.zip to zip all RDDs together, then convert to Rows
val rowRdd: RDD[Row] = rdds
  .map(_._2)
  .map(_.map(s => Seq(s)))
  .reduceLeft((rdd1, rdd2) => rdd1.zip(rdd2).map { case (l1, l2) => l1 ++ l2 })
  .map(Row.fromSeq)

// Create schema using the column names:
val schema: StructType = StructType(rdds.map(_._1).map(name => StructField(name, StringType)))

// Create DataFrame:
val result: DataFrame = spark.createDataFrame(rowRdd, schema)

result.show
// +------+------+------+
// |field1|field2|field3|
// +------+------+------+
// |     a|     1|     Q|
// |     b|     2|     W|
// |     c|     3|     E|
// +------+------+------+

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM