Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Spark reduce和聚合在同一数据集上_Scala_Apache Spark_Aggregate Functions - Fatal编程技术网

Scala Spark reduce和聚合在同一数据集上

Scala Spark reduce和聚合在同一数据集上,scala,apache-spark,aggregate-functions,Scala,Apache Spark,Aggregate Functions,我有一个文本文件,我读取它,然后使用split操作进行拆分。这将产生一个带有数组(A、B、C、D、E、F、G、H、I)的RDD 我想为每个键E(按键E减少)查找max(F)-min(G)。然后我想按键C组合结果值,并用相同的键连接每一行的这个求和结果 例如: +--+--+--+--+ | C| E| F| G| +--+--+--+--+ |en| 1| 3| 1| |en| 1| 4| 0| |nl| 2| 1| 1| |nl| 2| 5| 2| |nl| 3| 9| 3| |nl| 3|

我有一个文本文件,我读取它,然后使用
split
操作进行拆分。这将产生一个带有
数组(A、B、C、D、E、F、G、H、I)的RDD

我想为每个键
E
(按键
E
减少)查找
max(F)-min(G)
。然后我想按键
C
组合结果值,并用相同的键连接每一行的这个求和结果

例如:

+--+--+--+--+
| C| E| F| G|
+--+--+--+--+
|en| 1| 3| 1|
|en| 1| 4| 0|
|nl| 2| 1| 1|
|nl| 2| 5| 2|
|nl| 3| 9| 3|
|nl| 3| 6| 4|
|en| 4| 9| 1|
|en| 4| 2| 1|
+-----------+
应该导致

+--+--+-------------+---+
| C| E|max(F)-min(G)|sum|
+--+--+-------------+---+
|en| 1| 4           |12 |
|nl| 2| 4           |10 |
|nl| 3| 6           |10 |
|en| 4| 8           |12 |
+--+--+-------------+---+
解决这个问题的最好办法是什么?目前,我正试图通过运行来执行
max(F)-min(G)

val maxCounts = logEntries.map(line => (line(4), line(5).toLong)).reduceByKey((x, y) => math.max(x, y))
val minCounts = logEntries.map(line => (line(4), line(6).toLong)).reduceByKey((x, y) => math.min(x, y))

val maxMinCounts = maxCounts.join(minCounts).map{ case(id, maxmin) => (id, (maxmin._1 - maxmin._2)) }
然后
join
生成的RDD。然而,当我还想对这些值求和并将它们附加到现有数据集中时,这就变得很棘手了


我很想听到任何建议

假设,像您的示例数据一样,唯一的E永远不会跨越多个C。。。你可以这样做

import math.{max,min}

case class FG(f: Int, g: Int) {
  def combine(that: FG) =
    FG(max(f, that.f), min(g, that.g))
  def result = f - g 
}

val result = {
  rdd
  .map{ case Array(_, _, c, _, e, f, g, _, _) => 
    ((c, e), FG(f, g)) }
  .reduceByKey(_ combine _)
  .map{ case ((c, _), fg) =>
    (c, fg.result) }
  .reduceByKey(_+_)  
}

这种逻辑很容易在DataFrameAPI中实现。但您需要从数组中显式形成列:

val window = Window.partitionBy('C)

val df = rdd
  .map { case Array(_, _, c, _, e, f, g, _, _) => (c,e,f,g) }
  .toDF("C","E","F","G")
  .groupBy('C,'E)
  .agg((max('F) - min('G)).as("diff"))
  .withColumn("sum",sum('diff).over(window))   

使用Spark SQL DataFrame很容易,您可以将RDD转换为DataFrame并执行所有聚合操作。。尝试此链接为什么不将
math.max
math.min
合并到同一RDD中?谢谢您的建议。我将
sum(diff)
更改为
sum('diff)
Window.partitionBy('v)
更改为
Window.partitionBy('C)
,因为否则会导致错误。但是,当我尝试运行此代码时,我得到了以下错误:
scala.MatchError:[Ljava.lang.String;@f908897(属于[Ljava.lang.String;)
。使用
Window.partitionBy('v)
导致
org.apache.spark.sql.AnalysisException:无法解析给定输入列[C,E,diff];
。我使用Spark CSV阅读器解决了这个问题,而不是直接读取输入文件。这个问题可能与输入中的特殊字符有关。