RDD访问另一个RDD中的值

时间:2015-04-01 23:19:08

标签: scala apache-spark rdd

我有RDD需要访问其他RDD的数据。但是,我总是收到Task not Serializable错误。我扩展了Serializable类,但它没有用。代码是:

val oldError = rddOfRatings.aggregate(0.0)((accum, rating) =>
accum + calcError(rating.rating,
us.lookup(rating.user)(0),
it.lookup(rating.product)(0)).abs, _+_ ) / rddSize

usitrddOfRatings是其他RDD的地方。我不明白的是,如果RDD是不可变的,那么为什么不允许我允许我从另一个RDD内访问RDD?问题似乎在于usit,因为当我为本地集合删除它时,它可以正常工作。

谢谢。

2 个答案:

答案 0 :(得分:2)

由于必须捕获的变量(例如SparkContext),RDD确实是不可序列化的。要解决这个问题,将三个RDD连接在一起,您将在累加器闭包中获得所有必要的值。

答案 1 :(得分:1)

rdd.lookup 1是一项昂贵的操作,即使可能,您也可能不想这样做。

此外,"序列化" RDD没有意义,因为RDD只是对数据的引用,而不是数据本身。

这里采取的方法可能取决于这些数据集的大小。如果usit RDD与rddOfRatings的大小大致相同(根据预期的查找情况,它看起来是这样的),最好的方法是事先加入这些内容。

//请注意我并不知道您的收藏品的实际结构,因此请将此作为说明性示例

val ratingErrorByUser = us.map(u => (u.id, u.error))
val ratingErrorByProduct = it.map(i=> (i.id, i.error)) 
val ratingsBykey = rddOfRatings.map(r=> (r.user, (r.product, r.rating)))
val ratingsWithUserError = ratingsByKey.join(ratingErrorByUser)
val ratingsWithProductError = ratingsWithUserError.map{case (userId, ((prodId, rating),userErr))} => (prodId,(rating, userErr))}
val allErrors = ratingsWithProductError.join(ratingErrorByProduct)
val totalErr = allErrors.map{case (prodId,((rating, userErr),prodErr)) => calcError(userErr, math.abs(prodErr), rating)}.reduce(_+_)
val total = totalErr / rddOfRatings.count

使用Spark DataFrame API

可能会轻松得多

1如果必须进行查询(在这种情况下看起来不像!),请查看Spark IndexedRdd