SCALA:在一个列上分组,在另一列上求和

时间:2018-08-13 05:01:33

标签: scala apache-spark

我是Scala的新手。输入文件中包含的数据为:

a,abcd,1
a,efaf,3
b,xafsdf,2
b,fafdr,3

我需要如下输出:

a,4
b,5
object WordCount {
  def main(args: Array[String]): Unit = {`
  val conf = new SparkConf().setAppName("WordCount").setMaster("local")`
  val sc = new SparkContext(conf)`
  val dataRDD = sc.textFile("D:\\scala_samples\\moin.csv")`
  // dataRDD.collect().foreach(println(_))`
  val splitted = dataRDD.map(line => line.split(","))`
  val processed = splitted.map(x=>(x(0),x(2)))`

如何从这里继续?

3 个答案:

答案 0 :(得分:1)

只使用数据框语义。

首先将数据读取为数据框:

val spark = SparkSession.getOrCreate
val df = spark.read.csv(filename)
df.groupby("a").sum

编辑:对于RDD版本,请尝试:

processsed.reduceByKey(_ + _).

以上基本上假设已处理是一对RDD,并且您想为每个键(第一个元素)求和第二个元素的值。

答案 1 :(得分:0)

您必须使用reduceByKey()函数。请按以下步骤找到解决方案

//Creating sample rdd, you can use yours

val dataRDD=sc.parallelize(Array("a,abcd,1","a,efaf,3","b,xafsdf,2","b,fafdr,3"))

//Converting RDD[String] to RDD[(String,Int)] so you can apply reduceByKey function

val dataRDDMap=dataRDD.map(str=>str.split(",")).map(strArr=>(strArr(0),strArr(2).toInt))
val wcRDD=dataRDDMap.reduceByKey(_+_)

//Output:

scala>wcRDD.collect
res6: Array[(String, Int)] = Array((b,5), (a,4))  

答案 2 :(得分:0)

此方法与RDD的aggregateByKey操作一起使用。

val seqOp: (Int, (String, String, Int)) => Int = (accum, current) => accum + current._3
val combainOps: (Int, Int) => Int = (accum, current) => accum + current


val baseRDD = sc.textFile("\data.txt").map { x =>
  val splits = x.split(",")
  (splits(0), (splits(0), splits(1), splits(2).toInt))
}.aggregateByKey(0)(seqOp, combainOps)

baseRDD.foreach(println(_))

请注意,map操作会进行拆分,解析,将记录转换为键对值,而不是为每个步骤都创建不必要的RDD。

要将RDD保存到文件中,

baseRDD.saveAsTextFile("folder path")

有关更多信息,请参见document

更新

使用Rdd在多列上进行聚合有点麻烦,而使用SQL则简单而优雅。更新我的SQL解决方案。如果在rdd上需要同等的解决方案,请随时通知我。

import sql.implicits._
        Val df  = rdd.toDF("col1","col2","col3","col4","col5")

     import org. apache.spark.sql.functions.sum
        df.groupBy($"col1"). agg(sum("col3"),sum("col4"),sum("col5")).show