Scala Spark对数据帧行、单元格进行迭代

Scala Spark对数据帧行、单元格进行迭代,scala,apache-spark,Scala,Apache Spark,Spark初学者我编写了下面的代码来迭代数据帧Spark 2.4.0+Scala 2.12的行和列。 我已经计算了行数和单元格数作为一个健全性检查。 我惊讶地发现该方法返回0,即使计数器在迭代过程中递增 确切地说:当代码运行时,它会打印显示已找到的消息 第10、20、…、610行-如预期。 单元格100、200、…、1580- 正如所料。 迭代完成后,它打印找到的0个单元格,并返回0 我知道Spark是一个分布式处理引擎,并且代码并没有完全按照编写的方式执行——但是我应该如何看待这段代码呢 行/

Spark初学者我编写了下面的代码来迭代数据帧Spark 2.4.0+Scala 2.12的行和列。 我已经计算了行数和单元格数作为一个健全性检查。 我惊讶地发现该方法返回0,即使计数器在迭代过程中递增

确切地说:当代码运行时,它会打印显示已找到的消息

第10、20、…、610行-如预期。 单元格100、200、…、1580- 正如所料。 迭代完成后,它打印找到的0个单元格,并返回0

我知道Spark是一个分布式处理引擎,并且代码并没有完全按照编写的方式执行——但是我应该如何看待这段代码呢

行/单元格计数只是一个健康检查;实际上,我需要循环数据并积累一些结果,但如何防止Spark在迭代完成后立即将结果归零

  def processDataFrame(df: sql.DataFrame): Int = {
    var numRows = 0
    var numCells = 0
    df.foreach { row =>
      numRows += 1
      if (numRows % 10 == 0) println(s"Found row $numRows") // prints 10,20,...,610
      row.toSeq.foreach { c =>
        if (numCells % 100 == 0) println(s"Found cell $numCells") // prints 100,200,...,15800
        numCells += 1
      }
    }
    println(s"Found $numCells cells") // prints 0
    numCells
  }
Spark有一些变量,可以为您提供分布式环境中的计数等功能。您可以使用简单的long和int类型的累加器。即使是自定义数据类型的累加器也可以很容易地在Spark中实现。 在代码中,将计数变量更改为累加器变量(如下所示)将得到正确的结果

val numRows = sc.longAccumulator("numRows Accumulator")  // string name only for debug purpose
val numCells = sc.longAccumulator("numCells Accumulator")
df.foreach { row =>
  numRows.add(1)
  if (numRows.value % 10 == 0) println(s"Found row ${numRows.value}") // prints 10,20,...,610
  row.toSeq.foreach { c =>
    if (numCells.value % 100 == 0) println(s"Found cell ${numCells.value}") // prints 100,200,...,15800
    numCells.add(1)
  }
}
println(s"Found ${numCells.value} cells") // prints 0
numCells.value