Scala中的哪些数据结构是Python的嵌套字典或csv?

时间:2014-06-05 16:24:30

标签: python scala csv dictionary apache-spark

我在Spark shell中使用Scala。我将数据减少到RDD,byHour: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[47] at reduceByKey at <console>:16或者如果收集了数组byHour: Array[(String, Int)],则看起来像:

Array((6497+2006-03-19 20:00,13), (7511+2006-03-17 02:00,1), (13508+2006-03-26 10:00,4), (217+2006-05-16 16:00,1), (12404+2006-03-27 15:00,1), (9777+2006-05-14 09:00,1), (10291+2006-03-03 17:00,2), (4781+2006-05-10 14:00,2), (10291+2006-04-26 17:00,1), (15198+2006-04-26 12:00,1))

我想将它存储在Python或csv文件中的嵌套字典中。

在Python中我会创建

{"6497": {"2006-03-19 20:00": 13, "2006-03-19 22:00": 1}, "7511": {"2006-03-17 02:00": 1}...}

最后我想要

userid, 2006-03-17 01:00, 2006-03-17 02:00, ... , 2006-03-19 20:00, 2006-03-19 21:00, 2006-03-19 22:00
6497,0,0, ..., 13,0,1
7511,0,1, ..., 0,0,0

我不确定如何在Scala中到达那里。我想我需要一个列表或一组哈希映射或一个hashMap [String =&gt; HashMap中。


更新: byHour是RDD [(String,Int)]

val byUserHour = byHour.map(x => (x._1.split("\\+")(0),(x._1.split("\\+")(1),x._2)))
val byUser = byUserHour.groupByKey
val times = byHour.map(x => x._1.split("\\+")(1)).distinct.collect.sortWith(_ < _)
val broadcastTimes = sc.broadcast(times)
val userMaps = byUser.mapValues { 
  x => x.map{
    case(time,cnt) => time -> cnt
  }.toMap
}
val result = userMaps.map {
  case(u,ut) => (u +: broadcastTimes.value.map(ut.getOrElse(_,0).toString))}
val lines = result.map(_.mkString(","))
val header = List("userid") ::: times.toList

1 个答案:

答案 0 :(得分:2)

首先,您将拆分用户ID,因此您获得data: Seq[(String, String, Int)]。然后,按用户ID分组:

val byUser: Map[String, Seq[(String, String, Int)]] = data.groupBy(_._1)

现在我们可以为每个用户创建一个地图:

val userMaps: Map[String, Map[String, Int]] = byUser.mapValues {
  s => s.map {
    case (user, time, n) => time -> n
  }.toMap
}

对于最终格式化,您首先需要获取不同的时间戳,然后在每个用户的地图中查看这些时间戳:

val times: Seq[String] = data.map(_._2).toSet.toList
val result: Seq[Seq[String]] = userMaps.toSeq.map {
  case (u, ut) => (u +: times.map(ut.getOrElse(_, 0).toString))
}
val lines: Seq[String] = result.map(_.mkString(","))

希望这足以让你入门。您可以在http://twitter.github.io/scala_school/collections.html(以及许多其他地方)阅读有关Scala集合的更多信息。


以上所有内容都是本地计算 - 根本不分发。要以分布式方式执行相同操作,您可以在开始时将数据读入RDD(sc.textFile()),并执行大致相同的操作序列。

一个细微差别是,groupBy代替groupByKey,而RDD[A, B]的行为略有不同。从RDD[A, Iterable[B]]开始,您获得Map[A, Seq[(A, B)]],而不是times

主要区别在于您需要从群集中收集val times: Seq[String] = data.map(_._2).distinct.collect val broadcast = sc.broadcast(times) val result: RDD[Seq[String]] = userMaps.map { val times = broadcast.value case (u, ut) => (u +: times.map(ut.getOrElse(_, 0).toString)) } 到应用程序,然后将其广播到所有节点:

{{1}}