apache-spark - 在 Spark DataFrame 中计算大于 0 的值的更快方法?
问题描述
我有一个 Spark DataFrame
,其中所有字段都是整数类型。我需要计算有多少单个单元格大于 0。
我在本地运行,有DataFrame
17,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 计算怎么会这么快?
解决方案
该怎么办
import org.apache.spark.sql.functions.{col, count, when}
df.select(df.columns map (c => count(when(col(c) > 0, 1)) as c): _*)
为什么
您的两次尝试都会创建与列数成比例的作业数。单独计算执行计划和调度作业是昂贵的,并且会根据数据量增加大量开销。
此外,数据可能会在每次执行作业时从磁盘加载和/或解析,除非数据被完全缓存并具有显着的内存安全余量,以确保缓存的数据不会被驱逐。
这意味着在最坏的情况下,您使用的类似嵌套循环的结构在列数方面可能大致成二次方。
上面显示的代码同时处理所有列,只需要一次数据扫描。