我正在尝试使用Scala对日志数据执行一系列转换,而且我在匹配元组方面遇到了困难。我有一个包含用户ID,网址和日期的数据框。我可以将数据帧映射到RDD,并使用此映射按键减少:
val countsRDD = usersUrlsDays.map { case Row(date:java.sql.Date, user_id:Long, url:String) => Tuple2(Tuple2(user_id, url), 1) }.rdd.reduceByKey(_+_)
这给了我一个RDD((user_id,url),count):
scala> countsRDD.take(1)
res9: Array[((Long, String), Int)]
scala> countsRDD.take(1)(0)
res10: ((Long, String), Int)
现在我想通过url反转它来产生:
(url, [(user_id, count), ...])
我试过这个:
val urlIndex = countsRDD.map{ case Row(((user_id:Long, url:String), count:Int)) => Tuple2(url, List(Tuple2(user_id, count))) }.reduceByKey(_++_)
这会产生匹配错误:
scala.MatchError: ... (of class scala.Tuple2)
我已尝试使用显式和隐式类型对这两个地图调用进行了许多不同的排列,这似乎让我最远。我希望这里有人可以帮助我指出正确的方向。
答案 0 :(得分:2)
这样的事情应该有效:
countsRDD
.map{ case ((user_id, url), count) => (url, (user_id, count)) }
.groupByKey
countsRDD
RDD[((String, String), Int)]
不是RDD[Row]
。TupleN
。元组文字可以正常工作。countsRDD
是静态类型的(与RDD[Row]
不同),因此您不必指定类型。reduceByKey
进行列表连接。这是您可以采取的最糟糕的方法,并忽略了计算复杂性,垃圾收集器和常识。 如果您确实需要分组数据,请使用专为其设计的操作。