Scala 在同组RDD上迭代
我使用了一个cogroup函数并获得了以下RDD:Scala 在同组RDD上迭代,scala,apache-spark,Scala,Apache Spark,我使用了一个cogroup函数并获得了以下RDD: org.apache.spark.rdd.RDD[(Int, (Iterable[(Int, Long)], Iterable[(Int, Long)]))] 在映射操作之前,连接的对象将如下所示: RDD[(Int, (Iterable[(Int, Long)], Iterable[(Int, Long)]))] (-2095842000,(CompactBuffer((1504999740,1430096464017), (613904
org.apache.spark.rdd.RDD[(Int, (Iterable[(Int, Long)], Iterable[(Int, Long)]))]
在映射操作之前,连接的对象将如下所示:
RDD[(Int, (Iterable[(Int, Long)], Iterable[(Int, Long)]))]
(-2095842000,(CompactBuffer((1504999740,1430096464017), (613904354,1430211912709), (-1514234644,1430288363100), (-276850688,1430330412225)),CompactBuffer((-511732877,1428682217564), (1133633791,1428831320960), (1168566678,1428964645450), (-407341933,1429009306167), (-1996133514,1429016485487), (872888282,1429031501681), (-826902224,1429034491003), (818711584,1429111125268), (-1068875079,1429117498135), (301875333,1429121399450), (-1730846275,1429131773065), (1806256621,1429135583312))))
(352234000,(CompactBuffer((1350763226,1430006650167), (-330160951,1430320010314)),CompactBuffer((2113207721,1428994842593), (-483470471,1429324209560), (1803928603,1429426861915))))
现在我想做以下工作:
val globalBuffer = ListBuffer[Double]()
val joined = data1.cogroup(data2).map(x => {
val listA = x._2._1.toList
val listB = x._2._2.toList
for(tupleB <- listB) {
val localResults = ListBuffer[Double]()
val itemToTest = Set(tupleB._1)
val tempList = ListBuffer[(Int, Double)]()
for(tupleA <- listA) {
val tValue = someFunctionReturnDouble(tupleB._2, tupleA._2)
val i = (tupleA._1, tValue)
tempList += i
}
val sortList = tempList.sortWith(_._2 > _._2).slice(0,20).map(i => i._1)
val intersect = sortList.toSet.intersect(itemToTest)
if (intersect.size > 0)
localResults += 1.0
else localResults += 0.0
val normalized = sum(localResults.toList)/localResults.size
globalBuffer += normalized
}
})
//method sum
def sum(xs: List[Double]): Double = {//do the sum}
val globalBuffer=ListBuffer[Double]()
val joined=data1.cogroup(data2.map)(x=>{
val listA=x.。\u 2.\u 1.toList
val listB=x._2._2.toList
用于(元组i.。_1)
val intersect=sortList.toSet.intersect(itemToTest)
如果(intersect.size>0)
localResults+=1.0
else localResults+=0.0
val normalized=sum(localResults.toList)/localResults.size
globalBuffer+=标准化
}
})
//方法和
def sum(xs:List[Double]):Double={//do the sum}
在这篇文章的结尾,我希望加入的是一个具有双值的列表。但当我看到它时,它是一个单位。我也会说,这不是Scala的做法。如何获得
globalBuffer
作为最终结果。Hmm,如果我正确理解了您的代码,它将从以下改进中受益:
val joined = data1.cogroup(data2).map(x => {
val listA = x._2._1.toList
val listB = x._2._2.toList
val localResults = listB.map {
case (intBValue, longBValue) =>
val itemToTest = intBValue // it's always one element
val tempList = listA.map {
case (intAValue, longAValue) =>
(intAValue, someFunctionReturnDouble(longBvalue, longAValue))
}
val sortList = tempList.sortWith(-_._2).slice(0,20).map(i => i._1)
if (sortList.toSet.contains(itemToTest)) { 1.0 } else {0.0}
// no real need to convert to a set for 20 elements, by the way
}
sum(localResults)/localResults.size
})
rdd
的转换不会修改globalBuffer
。创建了globalBuffer
的副本并发送给每个工人,但是工人对这些副本的任何修改都不会修改驱动程序上存在的globalBuffer
(您在RDD
上的映射
之外定义的副本)。以下是我要做的(还有一些额外的修改):
val joined=data1.cogroup(data2)映射{x=>
val iterA=x.。\u 2.\u 1
val iterB=x.。\u 2.\u 2
变量计数,正计数=0
val templast=ListBuffer[(整数,双精度)]()
对于(tupleB@Null-Hypothesis),你能澄清一下你在之前的评论中的意思吗?你的意思是你在“循环”时想要某种连续的比例吗请进一步澄清。@Null假设是的,它在Scala中有效:函数体中最后一条指令的结果成为该函数返回的值。它将是RDD[Double],如果需要,您必须将其转换为一个列表。@Null假设,那么对于每个x,您需要一个单一的比例?如果,那么我认为Ashalynd或我的方法(对于一些小细节,它们几乎是相同的模)很好。你只需要做一个连接。收集
来获得一个本地收集,假设这是你最终想要的。@Null假设,忘记全局缓冲区
。请参阅我关于为什么这不起作用的答案。Ashalynd或我的代码创建的RDD
连接
将包含你想要的所有比例。如果您想在本地数组中使用它,那么只需使用vallocalJoined=joined.collect
。如果您需要在列表中使用它,那么请使用val localJoined=joined.collect.toList
。或者您可以将.collect.toList添加到joined的定义中,如果您愿意的话。@Null假设,请参阅代码前面的注释--a transforma aRDD
上的操作无法修改驱动程序上任何对象的状态(除非您使用的是累加器/可累加器
,在这种情况下,您不…我不建议这样做。)@如果您不知道,则为空假设(如果您知道,请原谅我),在Scala中,最后计算的值是函数返回的值。因此,上面的函数(传递到RDD
的map
方法中)将每个x
映射到positiveCount.toDouble/count
。应用于此函数的map
方法的结果将是包含这些比例的RDD
。
val joined = data1.cogroup(data2) map { x =>
val iterA = x._2._1
val iterB = x._2._2
var count, positiveCount = 0
val tempList = ListBuffer[(Int, Double)]()
for (tupleB <- iterB) {
tempList.clear
for(tupleA <- iterA) {
val tValue = someFunctionReturnDouble(tupleB._2, tupleA._2)
tempList += ((tupleA._1, tValue))
}
val sortList = tempList.sortWith(_._2 > _._2).iterator.take(20)
if (sortList.exists(_._1 == tupleB._1)) positiveCount += 1
count += 1
}
positiveCount.toDouble/count
}