我正在尝试计算特定日期特定物品的出现。
我输入的结构为Date\tItem1:AppearencesOfItem1,...,ItemN:AppearencesOfItemN
示例
20/10/2000\tItem1:1,Item2:5
20/10/2000\tItem1:2
21/10/2000\tItem1:5
为此,我创建了以下PairRdd结构:
[(20/10/2000, (Item1, 1))
(20/10/2000, (Item2, 5))
(20/10/2000, (Item1, 5))
(21/10/2000, (Item1, 5))]
,然后是groupByKey
,该日期导致:
[(20/10/2000, Iterable[(Item1, 1), (Item2, 5), (Item1, 5))
(21/10/2000, Iterable[(Item1, 5)]
此步骤后,我想做的就是减小这些对的值,并对具有相同密钥的项的外观求和,以使结果变为:
[(20/10/2000, Iterable[(Item1, 6), (Item2, 5))
(21/10/2000, Iterable[(Item1, 5)]
但是我还没有找到减少这些pairRdds值的方法。我的方法首先是错误的吗?
答案 0 :(得分:2)
可以通过两个步骤实现:
GroupBy(或为性能降低reduceBy)的第一列
val data = List(
("20/10/2000", "Item1", 1),
("20/10/2000", "Item2", 5),
("20/10/2000", "Item1", 5),
("21/10/2000", "Item1", 5)
)
val originalRDD = sparkContext.parallelize(data)
val sumRDD = originalRDD.map(v => ((v._1, v._2), v._3)).reduceByKey(_ + _)
sumRDD.map(v => ((v._1._1), (v._1._2, v._2))).groupByKey().foreach(println)
输出:
(21/10/2000,CompactBuffer((Item1,5)))
(20/10/2000,CompactBuffer((Item1,6), (Item2,5)))
答案 1 :(得分:1)
希望这会有所帮助,这也许不是他最优雅的方式,但似乎符合您的要求:
rdd.groupByKey.mapValues(x => x.groupBy(_._1).mapValues(x => x.map(_._2).sum))
首先将您的值映射到按itemId分组,然后在该分组列表上,再次映射值以仅保留第二个元素(整数),这样您就可以直接对其求和
输出:
scala> rdd.groupByKey.mapValues(x => x.groupBy(_._1).mapValues(x => x.map(_._2).sum)).foreach(println)
(21/10/2000,Map(Item1 -> 5))
(20/10/2000,Map(Item2 -> 5, Item1 -> 6))
修改
我是在RDD内创建地图,如果您希望将其作为List或仅执行toList
rdd.groupByKey.mapValues(x => x.groupBy(_._1).mapValues(x => x.map(_._2).sum).toList)