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