使用Scala在Spark中循环使用RDD

时间:2018-04-19 12:17:36

标签: scala loops bigdata rdd

所以我在Spark Shell中使用Scala进行了这个任务,我们给了一个~3M推文的tsv文件,我们应该估计下一个推文的位置(从我们写的文本文件中输入)在朴素贝叶斯估计上。这样,如果我写“请帮助我解决stackoverflow”,它将输出最有可能发布该位置的获胜者,例如:“伯明翰,0.2”

首先,我从tsv文件中获取数据并进行一些rdd转换:

val t = sc.textFile("PATH-TO-DATASET")
val s = t.map(_.split('\t')) //
val location = s.map(x => x(4))
val locAndTweetText = s.map(x => (x(4),x(10)))
val distinctLoc = location.distinct()

现在我想要做的但是无法弄清楚:我如何循环每个位置并输出相对于整个数据集的那个位置的分数?

我尝试了以下的变体:

for (e <- distinctLoc) {
  val a = location.filter(x => x == e).count()
  val b = a / t.count()
  println(b)
}

但我一直在犯错误。在此之后,我需要对每个位置的文件的输入字再次执行相同的操作,但是当我甚至没有单个工作时,我不能执行嵌套的for循环。任何人都有任何想法?

1 个答案:

答案 0 :(得分:2)

您正在使用RDD,而不是数组。你必须以不同的方式对待它们。具体来说,你不能像在这里那样将另一个rdd操作嵌套到彼此中。

看起来您正在尝试计算每个位置的数量。这是使用groupBy完成的,使用元素本身作为键,然后计算每个键的元素数。

val locationCounts = location.groupBy(identity).mapValues(iter => iter.length())

然后,您尝试计算这些计数的比率和总记录数。您可以在任何循环或其他rdd操作之外获得t的计数。

val totalCount = t.count()

最后,迭代locationCounts RDD并打印该值。

for((location, count) <- locationCounts){
  val ratio = count / totalCount.toDouble
  println(location + ": " + ratio)
}

如果您想在新的RDD中获取结果而不是仅仅打印出来,只需使用地图而不是foreach。

val locationRatios = locationCounts.map{
  case (location, count) => location -> (count / totalCount.toDouble)
}

或使用for version

val locationRatios = for((location, count) <- locationCounts) 
   yield location -> (count / totalCount.toDouble)

现在locationRatiosRDD[(String, Double)],其中包含每个位置的记录总数的比率。