我有一个表格
的(键,值)对的RDDRDD[(
scala.collection.immutable.Vector[(Byte, Byte)],
scala.collection.immutable.Vector[Int]
)]
其中key
是Vector[(Byte, Byte)]
而value
是Vector[Int]
。
例如,RDD的内容可以如下所示。
(Vector((3,3), (5,5)), Vector(1, 2)),
(Vector((1,1), (2,2), (3,3),(4,4), (5,5)), Vector(1, 3, 4, 2)),
(Vector((1,1), (2,3)), Vector(1, 4, 2)),
(Vector((1,1), (2,2), (5,5)), Vector(3, 5)),
我想对这个RDD进行操作,以便在结果RDD中,对于每个(键,值)对,满足以下条件。
当此RDD的键'k1'是此RDD的键'k2'的子集时,k1的值也应更新为包含k2的值,而k2的值将保持不变。
以上示例RDD将成为
(Vector((3,3), (5,5)), Vector(1, 2, 3, 4)),
(Vector((1,1), (2,2), (3,3), (4,4), (5,5)), Vector(1, 3, 4, 2))
(Vector((1,1), (2,3)), Vector(1, 4, 2))
(Vector((1,1), (2,2), (5,5)), Vector(1, 2, 3, 4, 5))
我问了一个类似的问题here。提供的解决方案如下(稍作修改以适应我的问题)。这适用于大型数据集但效率很低。
val resultPre = rddIn
.flatMap { case (colMapkeys, rowIds) =>
colMapkeys.subsets.tail.map(_ -> rowIds)
}
.reduceByKey(_ ++ _)
.join(rddIn map identity[(Seq[(Byte, Byte)], Vector[Int])])
.map{ case (key, (v, _)) => (key, v) }
implicit class SubSetsOps[T](val elems: Seq[T]) extends AnyVal {
def subsets: Vector[Seq[T]] = elems match {
case Seq() => Vector(elems)
case elem +: rest => {
val recur = rest.subsets
recur ++ recur.map(elem +: _)
}
}
}
生成所有密钥子集,然后通过加入原始RDD密钥对其进行过滤似乎是无效的。
我如何有效地处理这个问题?
答案 0 :(得分:1)
我认为你的问题基本上很难。你基本上有两种方法可以做到这一点:
生成所有子集键,合并值列表并收集任何给定子集的fina列表,然后仅加入现有子集。 (这就是你要做的)。
将每个条目与其他条目进行比较,查看一个键是否是另一个键的子集,然后合并按键生成的所有子集。这不会产生虚假的密钥中间排列。
哪一个更有效将取决于数据的性质(关键向量的大小,它们是彼此的子集的次数等)。
您可以尝试的其他优化是使数据更容易处理。例如,您可以安全地将内部坐标映射到整数(它们只是字节)。说(5,5)到5 * 1000 + 5 = 5005.因为整数比较比比较元组更容易,更快。
取决于您对密钥域的理解程度。如果此空间足够小,您可以尝试将密钥表示为位图或其他类似的位置。这些更改不会从根本上改变您拥有的密钥数量,但可能会使比较和其他操作更容易。