【问题标题】:Getting the mode from an RDD从 RDD 获取模式
【发布时间】:2019-09-06 04:26:02
【问题描述】:

我想使用 Spark + Scala 从 rdd 获取模式(最常见的数字)。

我可以通过以下方式得到它,但我认为这可能是一种更好的计算方法。最重要的是,如果多个值具有相同的重复次数,我需要将它们都返回。

让我们看看我的示例代码:

val l = List(3,4,4,3,3,7,7,7,9)
val rdd = spark.sparkContext.parallelize(l)
val grouped = rdd.map (e => (e, 1)).groupBy(_._1).map(e=> (e._1, e._2.size))
val maxRep = grouped.collect().maxBy(_._2)._2
val mode = grouped.filter(e => e._2 == maxRep).map(e => e._1).collect

结果是对的:

Array[Int] = Array(3, 7)

但是有没有更好的方法来做到这一点?我的意思是考虑性能,因为原始 RDD 会比这大得多。

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    这应该可以工作并且效率更高一些。 (仅当您确定元素的总数很小时)

    val counted = rdd.countByValue()
    val max = counted.valuesIterator.max
    val maxElements = count.collect { case (k, v) if (v == max) => k }
    

    如果可能有很多元素,请考虑这种内存安全的替代方案。

    val counted = rdd.map(x => (x, 1L)).reduceByKey(_ + _).cache()
    val max = counted.values.max
    val maxElements = counted.map { case (k, v) => (v, k) }.lookup(max)
    

    【讨论】:

    • 谢谢!,只是一个小细节:是lookup而不是lookUp
    • @mjbsgll 对,对不起。
    【解决方案2】:

    如何从双重 groupBy 中获取最大键值对?这对于更大的数据量更有效。

    rdd.groupBy(identity).mapValues(_.size).groupBy(_._2).max
    
    // res1: (Int, Iterable[(Int, Int)]) = (3,CompactBuffer((3,3), (7,3)))
    

    获取元素

    rdd.groupBy(identity).mapValues(_.size).groupBy(_._2).max._2.map(_._1)
    
    // res4: Iterable[Int] = List(3, 7)
    

    第一个groupBy 将元素放入(element -> count) 类型为Map[Int, Long],第二个groupBy(element -> count)count 分组,如(count -> Iterable((element, count)),然后只需max 即可获取密钥具有最大键值的-value 对,即count

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多