Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Apache Spark RDD中每个唯一键的和值_Scala_Apache Spark - Fatal编程技术网

Scala Apache Spark RDD中每个唯一键的和值

Scala Apache Spark RDD中每个唯一键的和值,scala,apache-spark,Scala,Apache Spark,我有一个RDD[(String,(Long,Long))]其中每个元素都不是唯一的: (com.instagram.android,(2,0)) (com.android.contacts,(6,1)) (com.android.contacts,(3,4)) (com.instagram.android,(8,3)) ... 因此,我想获得一个RDD,其中每个元素是每个唯一键的两个值的总和: (com.instagram.android,(10,3)) (com.android.contac

我有一个
RDD[(String,(Long,Long))]
其中每个元素都不是唯一的:

(com.instagram.android,(2,0))
(com.android.contacts,(6,1))
(com.android.contacts,(3,4))
(com.instagram.android,(8,3))
...
因此,我想获得一个
RDD
,其中每个元素是每个唯一键的两个值的总和:

(com.instagram.android,(10,3))
(com.android.contacts,(9,5))
...
这是我的密码:

val appNamesAndPropertiesRdd = appNodesRdd.map({
  case Row(_, appName, totalUsageTime, usageFrequency, _, _, _, _) => 
    (appName, (totalUsageTime, usageFrequency))
})

使用
reduceByKey

val rdd = appNamesAndPropertiesRdd.reduceByKey(
  (acc, elem) => (acc._1 + elem._1, acc._2 + elem._2)
)

reduceByKey
使用SCouto描述的
aggregateByKey
,但具有更具可读性的用法。就您的情况而言,
aggregateByKey
的更高级功能(由
reduceebykey
的更简单API隐藏)是不必要的

函数
aggregateByKey
是用于此目的的最佳函数

appNamesAndPropertiesRdd.aggregateByKey((0, 0))((acc, elem) => (acc._1 + elem._1, acc._2 +elem._2 ),(acc1, acc2) => (acc1._1 + acc2._1, acc1._2 + acc2._2))
此处解释:
aggregateByKey((0,0))
=>这是零值。将作为初始值的值。在本例中,由于需要加法,如果希望使用double而不是int,那么0,0将是初始值(0.0,0.0)

((acc,elem)=>(acc.\u 1+elem.\u 1,acc.\u 2+elem.\u 2)
=>第一个函数。要在同一分区中累加元素,累加器将保存部分值。由于elem是一个元组,您需要将它的每个部分添加到累加器的相应部分

(acc1,acc2)=>(acc1.\u 1+acc2.\u 1,acc1.\u 2+acc2.\u 2))
=>第二个函数。从每个分区累积累加器

试试这个逻辑

rdd.groupBy(_._1).map(x=> (x._1, (x._2.map(_._2).foldLeft((0,0)) {case ((acc1, acc2),(a, b))=> (acc1+a, acc2+b)} )))

首先,我不认为usageFrequency应该简单地相加

现在,让我们来看看你想做什么,你想按键添加东西,你可以做到

1.使用
groupByKey
然后
reduce
对组进行总结

val requiredRdd = appNamesAndPropertiesRdd
  .groupBy({ case (an, (tut, uf)) => an })
  .map({
    case (an, iter) => (
      an,
      iter
        .map({ case (an, tut, uf) => (tut, tf) })
        .reduce({ case ((tut1, tf1), (tut2, tf2)) => (tut1 + tut2, tf1 + tf2) })
    )
  })
或者使用
reduceByKey

val requiredRdd = appNamesAndPropertiesRdd
  .reduceByKey({
    case ((tut1, uf1), (tut2, uf2)) => (tut1 + tut2, tf1 + tf2)
  })
reduceByKey
是一个更好的选择,原因有二:

  • 它保存了一个不需要的
    操作
  • groupBy
    方法可能导致成本高昂的重组

  • 它将比reduceByKey
    慢。groupBy({case(an,tut,uf)=>an})
    不正常,OP有
    。groupBy({case(an,(tut,uf))=>an})
    @Fobi Acc表示累加器;)可能您指的是元组中第一个元素中的max。然后
    appnamesandpropertiesdd.reduceByKey((acc,elem)=>Math.max(acc,elem.\u 1))
    这里acc只是一个长元组,不是元组,但我们仍然减少元组,这就是为什么我调用
    。\u 1
    的原因elem@TGaweda如果我尝试,我会出现一个错误:重载方法值max和可选项:(x$1:Double,x$2:Double)Double(x$1:Float,x$2:Float)Float(x$1:Long,x$2:Long)Long(x$1:Int,x$2:Int)Int不能应用于((Long,Long),Long)@Fobi奇怪。请尝试
    appNamesAndPropertiesRdd.reduceByKey((acc,elem)=>(Math.max(acc.u.1,elem.u.1),Math.max(acc.u.2,elem.u.2)).map(x=>(x.u.1,x.u.2.\u.u.I)
    @TGaweda我拥有:值映射不是(Int,Int)的成员可能原因:可能在“值映射”之前缺少分号?@Fobi在
    之前加上额外的
    -type错误;)