Scala 访问地图中的另一个rdd

Scala 访问地图中的另一个rdd,scala,apache-spark,Scala,Apache Spark,以下是我的示例数据: | rdd1 | | .... | | 10 | | 200 | | 350 | | 400 | | 1000 | | 1500 | | ..... | | rdd2 | | label | features | | .... | ....................... | | 0 | 1 10 30 100 200 450 600 | | 0 | 200 300 400

以下是我的示例数据:

| rdd1  |
| ....  |
| 10    |
| 200   |
| 350   |
| 400   |
| 1000  |
| 1500  |
| ..... |



| rdd2  |
| label | features                 | 
| ....  | .......................  |
|   0   | 1 10 30 100  200 450 600 |
|   0   | 200 300 400              |   
|   1   | 200 350 450              |
|   1   | 400 600 700              |
|  .... | ........................ |
我想计算以下内容:对于rdd1的每个元素,找出如何 它多次出现在rdd2中每个标签值的功能中。我 需要这样一个元组(#of times显示为标签0,#times 与标签1)一起出现,因此在上面的示例中,10与标签一起出现1次 用标签1标记0和0次,10次为(1,0)。200出现 2次使用标签0,1次使用标签1,因此对于 200

此外,我还想找出rdd1中每个元素的find out 有多少次它没有出现在rdd2中的特性中 标签值。我需要一个这样的元组(#的时间不会与 标签0,#次不与标签1一起出现)。所以在上面 例如,对于10我应该回去,它一次都没有出现 使用标签1(1,2)标记和两次

我计划按键使用聚合

val initialCount : collection.mutable.ListBuffer[Int] = ListBuffer(0, 0)
val addToCounts = (s: collection.mutable.ListBuffer[Int], label:Int) => if (label == 1) s(0) += 1 else s(1) += 1
val sumPartitionCounts = (p1: collection.mutable.ListBuffer[Int], p2: collection.mutable.ListBuffer[Int]) => ListBuffer((p1(0) + p2(0)),(p1(1) + p2(1)))
但是,我读到,不允许在另一个rdd的映射函数中访问rdd。任何关于我如何解决这个问题的想法都将非常好

  • 广播变量-如果rdd2足够小,则将其广播到每个节点,并将其用作rdd1.map或
  • Join-连接键值rdds
  • 您必须重新构造rdd2,以获得广播var查找或连接所需的键。如果rdd2是RDD[label,Array(feature)],我会尝试得到一个RDD[feature,label],如下所示:

    然后使用aggregateByKey创建RDD[feature,Map[label,frequency]]

        val initialMap = scala.collection.mutable.Map.empty[String, Int]
        val addToMap = (x: scala.collection.mutable.Map[String, Int], y: String) => {
            if(x.contains(y))
                x += ((y, x.get(y).get+1))
            else
                x += ((y, 1))
            }
        val mergeMaps = (x: scala.collection.mutable.Map[String, Int], y: scala.collection.mutable.Map[String, Int]) => {
            x ++= y
        }
        val rdd2Aggregated: RDD[String, scala.collection.mutable.Map[String,Int] = 
          rdd2Mapped.aggregateByKey(initialMap)(addToMap, mergeMaps)
    
    现在,要么广播rdd2Aggregated,要么将rdd1与rdd2Aggregated连接起来,并使用Map[label->frequency]获得所需的结果

    对于问题的第二部分,以几乎类似的方式转换rdd2,但每个标签只具有不同的特性

        val rdd2Mapped: RDD[String,String] = rdd2.flatMap(x => x._2.distinct.map(y => (y,x._1)))
    
    像第一部分一样获取RDD[feature,Map[label,frequency]]。这将为您提供功能在rdd2中出现的次数。现在,从rdd2中获取每个标签的行数(rdd2中标签的简单字数)。您可以像以前一样使用这个新的RDD2聚合来连接rdd1,并进一步使用wordcount查找映射来连接结果rdd(如果wordcount查找映射足够小,也可以广播wordcount查找映射)。现在,对于每个功能,您都会得到标签和频率的映射。从查找映射的相应标签计数中减去每个标签的频率,以获得所需的答案


    如果在给定的特征中,标签(标签,频率)中不存在标签,则认为该频率为0。请确保考虑这个边缘情况。

    如果RDD足够小以适合于每个节点,那么您可以使用广播变量更新问题。谢谢你的想法。更新我的答案。这听起来很像一个hw q,所以我没有给你完整的代码,只是一个演练。mergeMaps函数应该更新为:val mergeMaps=(map1:collection.mutable.Map[Int,Int],map2:collection.mutable.Map[Int,Int])=>{map1++map2.Map{case(k,v)=>k->(v+map1.getOrElse(k,0))}
        val rdd2Mapped: RDD[String,String] = rdd2.flatMap(x => x._2.distinct.map(y => (y,x._1)))