我有一段伪代码,我一直试图在Spark中实现(目前使用Scala,但很乐意在需要时使用其他语言)大约一个星期,我完全陷入困境。导致我出现问题的伪代码部分是(对图像道歉,但没有MathOverflow的LaTeX选项,它似乎最清楚):pseudocode
id1
,id2
,ob
,x
和y
。Window
分区(id1
,id2
),每个窗口都有多个(x
:整数,y
:整数和ob
:Double)构成一个单元格或c
。k = 1 ... m
,其中m
是窗口中的行数。st
值会受到影响,但过去的工作表明它在最终结果中没有可观察到的差异。)st
> 0是K
的一部分。由于st
> = 0,因此包含所有先前计算的行似乎是安全的。alpha
是固定参数。Dis_grid
目前是x
和y
坐标之间的欧几里德距离UDF,但如果这样可以使实施更容易,则它可以是不同的距离度量。我无法弄清楚如何:
st
来计算下一行的st
。st
公式的一部分。非常感谢任何帮助。
答案 0 :(得分:0)
我很难准确地遵循你想要做的事情(我认为命令在组/窗口内重要),所以这可能不对,但这些是我的想法。首先,我认为在Dataset
操作而不是DataFrame
操作方面,很多更容易思考。 (如果你想在DataFrame世界中这样做,我想你想看一下用户定义的聚合函数(UDAF)。)因为DataFrame
只是Dataset[Row]
,所以它都是相当于,但我要定义一个Cell
案例类并使用Dataset[Cell]
来简化事情,所以请放纵我。
case class Cell(id1: Int, id2: Int, ob: Double, x: Int, y: Int)
想象一下,我们有一个Dataset[Cell]
,称之为ds
。我们希望通过成对(id1,id2)
对其进行分组,然后在每个组上应用一些函数(如果f
调用),最后得到Dataset[(Cell, Double)]
。 (我认为这就是你想要的。在这种情况下,我很难看到组内行/单元的顺序无关紧要。)这相当于
ds.groupByKey(c => (c.id1, c.id2).flatMapGroups(f)
那么f
是什么?它需要为组中的每个单元格计算st
。如果我正确理解,则求和的工作方式如下:对于单元格i
,对所有st(j) * alpha^dist(i, j)
求和j < i
。从单元格的观察值中减去该总和,并从0减去最大值,得到st
。假设你有一个函数dist
来计算两个单元格之间的距离,作为一个函数,所有单元格,先前计算的st
和单元格c
,求和项可以用作:
def stSum(cells: List[Cell], sts: List[Double], c: Cell): Double =
sts.zipWithIndex.map{ case (st, l) =>
st * math.pow(alpha, dist(c, cells(l)))
}.sum
然后,对于单元格c
,st
为math.max(0, c.ob - stSum(cells, sts, c))
,其中cells
是该组中的所有单元格,sts
是一个列表&#34;早期&#34;的st
值细胞。然后,我们可以使用st
计算foldLeft
s的(有序)列表:
cells.foldLeft(List()){ case (sts, c) =>
sts :+ math.max(0, c.ob - stSum(cells, sts, c))
}
然后我们可以汇编f
:
def f(key: (Int, Int), cellIterable: Iterable[Cell]): List[(Cell, Double)] = {
val cells = cellIterable.toList
val sts = cells.foldLeft(List()){ case (stAcc, c) =>
stAcc :+ math.max(0, c.ob - stSum(cells, stAcc, c))
}
cells.zip(sts)
}
我们需要将cellIterable
转换为列表,因为我们需要通过索引访问其元素,因此我们需要一个支持它的类型。它通常在Scala中更快地添加到列表而不是追加,并且可以反向建立st
的列表,但它需要一些索引杂耍。最后需要注意的是,f
中的flatMapGroups
需要使用元组,而我上面写的f
没有,所以你最终得到了
ds.groupByKey(c => (c.id1, c.id2).flatMapGroups(Function.tupled(f))