我是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)))`
如何从这里继续?
答案 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