我拿了一个字符串然后切片,所以我只有那个字符串的第一个字母。我在计算每个关键字的出现次数。我有可行的代码,但我认为它不是最优化的。我这样说是因为在python中我使用了一个名为counter的函数,它不再需要执行额外的.groupByKey(),顺便说一句,键是列号。
val firstLetter = stringRDD.map(x => (x._1, x._2.slice(0,1)))
.groupBy(identity).mapValues(_.size)
.map(x => (x._1._1, (x._1._2, x._2)))
.groupByKey().collect()
最后我的输出如下所示(例如Key 50,有4488个字符串以0' s开头,而key 13有4个A' s,1个D和4483 T' ; s):
firstLetter: Array[(Int, Iterable[(String, Int)])] = Array(
(50,CompactBuffer((0,4488))), (0,CompactBuffer((D,4488))),
(51,CompactBuffer((X,2), (T,4486))), (32,CompactBuffer((6,4488))),
(13,CompactBuffer((A,4), (D,1), (T,4483))), (53,CompactBuffer((2,4488))),
(54,CompactBuffer((0,4488))), (14,CompactBuffer((T,4488))),
(45,CompactBuffer((A,4), (T,4484))), (47,CompactBuffer((2,4488))),
(48,CompactBuffer((0,4488))), (49,CompactBuffer((2,4488))))
示例数据:
res3: Array[(Int, String)] = Array((0,D), (13,D), (14,T),
(32,6393050780099594), (45,T), (47,2013-06-17 12:37:29.954597), (48,0),
(49,2013-06-17 12:37:29.954597), (50,0), (51,T), (53,2),
(54,078009959499), (0,D), (13,A), (14,T), (32,6393050780099586), (45,A),
(47,2013-06-17 12:37:29.718432), (48,0), (49,2013-06-17 12:37:29.718432))
业务用例:当我分析数百万条记录时,我正在查看一个姓氏为AC的文件,我注意到第13列(姓氏)有一堆不是AC的名字我可以标记这是错误的。同样,第50列是帐户名称,它们始终以0开头。
旁注:找不到太多信息,但什么是紧凑型缓冲区?
答案 0 :(得分:2)
这对您有何帮助:
stringRDD.aggregateByKey(Map[Char, Int]())(
(accum, value) => accum.get(value.head) match {
case None => accum + (value.head -> 1)
case Some(count) => accum + (value.head -> (count + 1))
},
(accum1, accum2) => accum1 ++ accum2.map{case(k,v) => k -> (v + accum1.getOrElse(k, 0))}
)
哦,这是CompactBuffer
答案 1 :(得分:0)
这个替代方案避免了问题中的第一个groupByKey
,因此它应该表现得更好。我不认为我们可以避免在最后累积值 - 因为问题 - 需要按键组织所有字母计数值。
val letterByKey = rdd.map(elem => ((elem._1, elem._2.head), 1))
val letterCount = letterByKey.reduceByKey(_ + _).map{case ((key,str),count) => (key,(str,count))}
val letterCountByKey = letterCount.groupByKey()