所以我在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循环。任何人都有任何想法?
答案 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)
现在locationRatios
是RDD[(String, Double)]
,其中包含每个位置的记录总数的比率。