Spark RDD:填写不规则的时间序列

时间:2015-10-23 03:00:36

标签: scala apache-spark rdd

所以我有一个带有不规则时间序列数据的RDD:

1,< value1>
4,< value4>
6,< value6>
..等

我需要将其填写到常规时间序列中:

1,< value1>
2,< value1>
3,< value1>
4,< value4>
5,< value4>
6,< value6>
..等

到目前为止,我已经创建了一个带有1,2,3,4,5,6的RDD,然后将leftOuterJoin编辑为原始RDD,这给了我:

1,< value1>
2,< None>
3,< None>
4,< value4>
5,< None>
6,< value6>
..等

所以我面临的问题是用前一个非空行的值填充2,3,5。

我更愿意在不使用sparkSQL的情况下在RDD级别上执行此操作,这当然是最后的选择。去scala数组级别并不是非常有吸引力,因为对于性能问题,我宁愿将它保持在RDD级别。

由于

1 个答案:

答案 0 :(得分:2)

没有初始join的相对简单的解决方案。让我们从伪数据和辅助函数开始:

val rdd = sc.parallelize(Seq(
    (3L, 1.0), (1L, 4.0), (5L, 3.6), (7L, 0.2), (8L, 0.0)))

def fillTimePoints(xs: Array[(Long, Double)]) = xs match {
  case Array((xTime, xValue), (yTime, _)) => {
    val diff = yTime - xTime

    if (diff == 0) Seq((xTime, xValue))
    else (xTime, xValue) +: (1 until diff.toInt)
      .map(_.toLong)
      .map(i => (i + xTime, xValue))
  }

  case _ => Seq.empty[(Long, Double)]
}

现在剩下的就是滑过已排序的RDD:

import org.apache.spark.mllib.rdd.RDDFunctions._

rdd.sortBy(_._1).sliding(2).flatMap(fillTimePoints).collect

//  Array[(Long, Double)] = Array((1,4.0), (2,4.0), (3,1.0), 
//    (4,1.0), (5,3.6), (6,3.6), (7,0.2))

注意:

  • sliding是开发人员API的一部分。它的类中的大多数方法在最近的版本中已被弃用。它仍然可以从头开始编码,但现在它应该可以工作,

  • 您可能更喜欢使用RangePartitioner后跟repartitionAndSortWithinPartitions而不是排序。然后,您可以使用mapPartitionspreservePartitioning设置为true来应用本地滑动,最后填补空白(再次preservePartitioning)。它需要更多工作,但您可以使用RangePartitioner分区输出可能有用的输出。