如何聚合+;scala中的分组?
我有以下数据:如何聚合+;scala中的分组?,scala,Scala,我有以下数据: val Cars_tmp = List("Cars|10|Paris|5|Type|New|3", "Cars|15|Paris|3|Type|New|5", "Cars|20|London|10|Type|New|2", "Cars|40|London|40|Type|New|1") 我想计算每个城市的平均汽车数量。 请注意: 汽车数量(6)=汽车数量和汽车数量(2).汽车数量(2)=城市 我试过
val Cars_tmp = List("Cars|10|Paris|5|Type|New|3", "Cars|15|Paris|3|Type|New|5", "Cars|20|London|10|Type|New|2", "Cars|40|London|40|Type|New|1")
我想计算每个城市的平均汽车数量。
请注意:
汽车数量(6)=汽车数量和汽车数量(2).汽车数量(2)=城市
我试过这个:
val aggregate = Cars_tmp.map(r => r.split("[|]")(6).toInt).par.aggregate((0, 0))(
(s, r) =>(s._1 + r , s._2 + 1),
(s,r) => (s._1 + r._1, s._2 + r._2)
)
val average: Float = aggregate._1.toFloat/ aggregate._2.toFloat
println("aggregate value" + aggregate)
println("average value" + average)
我有以下结果:
aggregate value (11,4)
average value 2.75
这将计算平均汽车数量。
我怎样才能包括按城市分组(按汽车分组)分割(“|”)(2))
谢谢你的回答
Cars_tmp
.map(x => {
(x.split('|')(2), x.split('|')(6).toInt)
})
.groupBy { case (city, _) => city }
.map { case (_, xs) =>
xs
.map(x => x._2)
.foldLeft(0.0f) { case (acc, x) => acc + (x / xs.size.toFloat) }
}
您可以提取(城市,汽车数量)的两个元组,然后使用groupBy
创建Map[String,List[(String,Int)]
,其中键为城市,值为汽车数量序列
然后使用map
计算平均值
结果是:
List(1.5F, 4.0F)
使用df(“城市”、“全国广播公司”)
检查平均聚合函数:
scala doc:谢谢您的回答。这对我很有帮助。
mapValues
是懒惰的,所以这会在每次访问地图时计算xs.map(u._2).sum.toFloat/xs.length
(代码在很多方面都非常低效)@LuisMiguelMejíaSuárez感谢您指出。实际上,在这种情况下,transform
更好,因为mapValues
将重新计算每次访问的平均值。我编辑了我的答案。还有什么其他方法可以提高性能?@etherealyn什么是转换
?也许你的意思是地图其他提高性能的方法包括使用foldLeft
而不是sum
和size
一次性计算平均值,以及将列表转换为map
+groupBy
之前的懒散列表,一次性执行这两个操作。谢谢您的回答。目前我只在Scala工作,不使用Spark。你有只使用Scala的想法吗?这是Scala。如果你不使用spark,为什么要使用ApacheSpark?我更喜欢使用Scala。但我不知道使用Scala是否可以进行聚合,是否必须使用Spark。这就是为什么我用Spark来标记它,以使它有其他的想法。而且我有一个列表,而不是一个数据框。首先,我必须将列表转换为DataFrame。val a=sc.parallelize(Cars_tmp)val b=a.map(x=>x.split(“|”).toDF.show(false)b.printSchema。我在数据帧中有一个元素数组,要进行解决方案中提到的攻击并不容易。将该字符串解析为一个case类,这样处理就更容易了。@LuisMiguelMejíaSuárez感谢您的回答。好的,我试试看。@LuisMiguelMejíaSuárez你能用一个例子解释一下你将如何使用case类吗?
df
.groupBy("city")
.agg(
avg(col("nbCars")).as("average_nb_cars")
)