对于以下两种检查数据帧是否为空的方法:
df.isEmpty
df.limit(1).count == 0
我看到
df.isEmpty
具有以下实现: def isEmpty: Boolean = withAction("isEmpty", limit(1).groupBy().count().queryExecution) { plan =>
plan.executeCollect().head.getLong(0) == 0
}
看起来它不只是直接计数。
groupBy
背后的想法是什么?只是为了获取数据框?为什么使用
queryExecution
计划? 最佳答案
在这篇文章中,我看到了三个不同的问题。
表演节目
如果仔细检查源代码,您会发现 df.count
所做的groupBy
与获取RelationalGroupedDateset的相同。
因此,如果我们比较两个实现:
def isEmpty: Boolean = withAction("isEmpty", limit(1).groupBy().count().queryExecution) {
plan => plan.executeCollect().head.getLong(0) == 0
}
def count(): Long = withAction("count", groupBy().count().queryExecution) { plan =>
plan.executeCollect().head.getLong(0)
}
df.isEmpty
和df.limit(1).count() == 0
在幕后的行为完全相同。但是,为了清楚起见,我会选择
df.isEmpty
。为什么使用
queryExecution
计划?查询执行计划是具有全局执行计划所需的属性。
每次完成转换后,此转换都会升级
queryExecution
。每次执行操作时,都会检索
queryExecution
,然后Catalyst计划对其进行优化。groupBy
背后的想法是什么?count
方法创建一个带有单个组的 RelationalGroupedDataset
。然后用Literal(1)
填充该组,然后同时按键减少(它不包含键,因此减少了每一列),以得到一个带有称为“count”的单列且只有一行包含count的DataFrame
。 (这就是为什么在df.count
实现中我们可以看到.head.getLong(0)
的原因此实现使您可以在每个分区中同时减少数据量,而无需创建要计数的迭代器。