首页 > 解决方案 > 在 Spark DataFrame 中计算大于 0 的值的更快方法?

问题描述

我有一个 Spark DataFrame,其中所有字段都是整数类型。我需要计算有多少单个单元格大于 0。

我在本地运行,有DataFrame17,000 行和 450 列。

我尝试了两种方法,都产生缓慢的结果:

版本 1:

(for (c <- df.columns) yield df.where(s"$c > 0").count).sum

版本 2:

df.columns.map(c => df.filter(df(c) > 0).count)

此计算需要 80 秒的挂钟时间。使用 Python Pandas,只需几分之一秒。我知道对于小型数据集和本地操作,Python 可能会表现得更好,但这似乎很极端。

尝试进行 Spark 到 Spark 的比较,我发现在相同的数据(转换为 RowMatrix)上运行 MLlib 的 PCA 算法只需不到 2 秒!

我应该使用更有效的实现吗?

如果不是,那么看似复杂得多的 PCA 计算怎么会这么快?

标签: apache-sparkapache-spark-sql

解决方案


该怎么办

import org.apache.spark.sql.functions.{col, count, when}

df.select(df.columns map (c => count(when(col(c) > 0, 1)) as c): _*)

为什么

您的两次尝试都会创建与列数成比例的作业数。单独计算执行计划和调度作业是昂贵的,并且会根据数据量增加大量开销。

此外,数据可能会在每次执行作业时从磁盘加载和/或解析,除非数据被完全缓存并具有显着的内存安全余量,以确保缓存的数据不会被驱逐。

这意味着在最坏的情况下,您使用的类似嵌套循环的结构在列数方面可能大致成二次方。

上面显示的代码同时处理所有列,只需要一次数据扫描。


推荐阅读