PySpark DataFrame的cube方法返回重复的null值

4
我有以下数据(您可以通过复制和粘贴来复制它):
from pyspark.sql import Row
l = [Row(value=True), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=None), Row(value=True), Row(value=None), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=None), Row(value=None), Row(value=None), Row(value=None), Row(value=True), Row(value=None), Row(value=True), Row(value=True), Row(value=True), Row(value=True), Row(value=True), Row(value=None), Row(value=None), Row(value=None), Row(value=True), Row(value=None), Row(value=True), Row(value=None)]
l_df = spark.createDataFrame(l)

让我们来看一下 l_df 的模式:
l_df.printSchema()

root
|-- value: boolean (nullable = true)

现在我想使用 cube() 函数来计算 value 列中每个不同值的频率:

l_df.cube("value").count().show()

但我看到两种类型的null值!

+-----+-----+
|value|count|
+-----+-----+
| true|   67|
| null|  100|
| null|   33|
+-----+-----+

为了验证我实际上没有两种类型的null

l_df.select("value").distinct().collect()

确实只有一种类型的null

[Row(value=None), Row(value=True)]

再次确认一下:

l_df.select("value").distinct().count()

它返回2

我还注意到len(l)100,而第一个null等于这个数字。为什么会发生这种情况?

系统信息:Spark 2.1.0,Python 2.7.8,[GCC 4.1.2 20070626 (Red Hat 4.1.2-14)] on linux2


目前无法测试我的环境,但为什么不直接执行 l_df.groupBy('value').count().show() 呢? - pault
是的,那样做可以。但是我仍然想弄清楚为什么 cube() 不起作用... - versatile parsley
2个回答

1
这不是两种类型的空值,而是不同级别聚合的结果。正如立方体、滚动和groupBy运算符之间的区别是什么?中所解释的那样,您的cube应用程序等同于:
SELECT NULL AS value, COUNT(*) FROM df
UNION ALL
SELECT value, COUNT(*) FROM df GROUP BY value

第一个查询生成元组(null, 100) (记录总数),其中NULL只是一个占位符;第二个查询生成元组(true, 67)(null, 33),其中NULLvalue列的一种级别。
使用grouping(或grouping_id)非常容易进行检查:
from pyspark.sql.functions import grouping, count

l_df.cube("value").agg(count("*"), grouping("value")).show()
# +-----+--------+---------------+
# |value|count(1)|grouping(value)|
# +-----+--------+---------------+
# | true|      67|              0|
# | null|     100|              1|
# | null|      33|              0|
# +-----+--------+---------------+

0

df.groupBy('value').count().show() 就像 @pault 所说的那样。

如果是 cube 的情况,添加一个 "filter" 方法对我很有用。

df.cube("value").count().filter(  col('count')<df.count()  ).show()

但是会增加一个额外的过程。请看我使用cube()函数时的工作截图。

See my example


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接