Spark - 计算每日事件的最大发生次数

时间:2017-08-31 07:27:32

标签: scala apache-spark

我有以下RDD[String]

1:AAAAABAAAAABAAAAABAAABBB  
2:BBAAAAAAAAAABBAAAAAAAAAA    
3:BBBBBBBBAAAABBAAAAAAAAAA

第一个数字应为days,以下字符为events

我必须计算每个事件最多发生的日期。 此数据集的预期结果应为:

{ "A" -> Day2 , "B" -> Day3 }

(A在第2天重复10次,第3天重复10次)

我正在拆分原始数据集

val foo = rdd.map(_.split(":")).map(x => (x(0), x(1).split("")) )

什么是计数和聚合的最佳实现?

感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

这应该可以解决问题:

import org.apache.spark.sql.functions._

val rdd = sqlContext.sparkContext.makeRDD(Seq(
  "1:AAAAABAAAAABAAAAABAAABBB",
  "2:BBAAAAAAAAAABBAAAAAAAAAA",
  "3:BBBBBBBBAAAABBAAAAAAAAAA"
))

val keys = Seq("A", "B")

val seqOfMaps: RDD[(String, Map[String, Int])] = rdd.map{str =>
  val split = str.split(":")
  (s"Day${split.head}", split(1).groupBy(a => a.toString).mapValues(_.length))
}

keys.map{key => {
  key -> seqOfMaps.mapValues(_.get(key).get).sortBy(a => -a._2).first._1
}}.toMap

答案 1 :(得分:0)

需要完成的处理包括将数据转换为易于应用于以下函数的rdd:查找列表的最大值 我将尝试逐步解释

我使用了“A”和“B”字符的伪数据。

foo rdd是第一步它会给你RDD [(String,Array [String])] 让我们为Array [String]

提取每个char
val res3 = foo.map{case (d,s)=> (d, s.toList.groupBy(c => c).map{case (x, xs) => (x, xs.size)}.toList)}

(1,List((A,18), (B,6)))
(2,List((A,20), (B,4)))
(3,List((A,14), (B,10)))

接下来,我们将flatMap over values来扩展我们的rdd by char

res3.flatMapValues(list => list)

(3,(A,14))
(3,(B,10))
(1,(A,18))
(2,(A,20))
(2,(B,4))
(1,(B,6))

重新排列rdd以便更好看

res5.map{case (d, (s, c)) => (s, c, d)}

(A,20,2)
(B,4,2)
(A,18,1)
(B,6,1)
(A,14,3)
(B,10,3)

现在我们被char

分组
res7.groupBy(_._1)

(A,CompactBuffer((A,18,1), (A,20,2), (A,14,3)))
(B,CompactBuffer((B,6,1), (B,4,2), (B,10,3)))

最后,我们采用每行的最大值计数

res9.map{case (s, list) => (s, list.maxBy(_._2))}

(B,(B,10,3))
(A,(A,20,2))

希望这个帮助

答案 2 :(得分:0)

以前的答案很好,但我更喜欢这样的解决方案:

val data = Seq(
  "1:AAAAABAAAAABAAAAABAAABBB",
  "2:BBAAAAAAAAAABBAAAAAAAAAA",
  "3:BBBBBBBBAAAABBAAAAAAAAAA"
)
val initialRDD = sparkContext.parallelize(data)

// to tuples like (1,'A',18)
val charCountRDD = initialRDD.flatMap(s => {
  val parts = s.split(":")
  val charCount = parts(1).groupBy(i => i).mapValues(_.length)
  charCount.map(i => (parts(0), i._1, i._2))
})

// group by character, and take max value from grouped collection
val result = charCountRDD.groupBy(i => i._2).map(k => k._2.maxBy(z => z._3))
result.foreach(println(_))

结果是:

(3,B,10)
(2,A,20)