所以我有一个带有不规则时间序列数据的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级别。
由于
答案 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
而不是排序。然后,您可以使用mapPartitions
将preservePartitioning
设置为true来应用本地滑动,最后填补空白(再次preservePartitioning
)。它需要更多工作,但您可以使用RangePartitioner
分区输出可能有用的输出。