计算 PySpark 列中的非空值数量

new*_*eaf 7 null count apache-spark apache-spark-sql pyspark

我有一个包含空值的数据框:

from pyspark.sql import functions as F
df = spark.createDataFrame(
    [(125, '2012-10-10', 'tv'),
     (20, '2012-10-10', 'phone'),
     (40, '2012-10-10', 'tv'),
     (None, '2012-10-10', 'tv')],
    ["Sales", "date", "product"]
)
Run Code Online (Sandbox Code Playgroud)

我需要计算“销售额”列中的非空值。

我尝试了3种方法。

第一个我做对了:

df.where(F.col("sales").isNotNull()).groupBy('product')\
  .agg((F.count(F.col("Sales")).alias("sales_count"))).show()

# product   | sales_count
# phone     |  1
# tv        |  2
Run Code Online (Sandbox Code Playgroud)

第二个是不正确的:

df.groupBy('product')\
  .agg((F.count(F.col("Sales").isNotNull()).alias("sales_count"))).show()

# product   | sales_count
# phone     |  1
# tv        |  3
Run Code Online (Sandbox Code Playgroud)

第三次,我得到了错误:

 df.groupBy('product')\
   .agg((F.col("Sales").isNotNull().count()).alias("sales_count")).show()
Run Code Online (Sandbox Code Playgroud)

类型错误:“列”对象不可调用

第二种和第三种方法可能会导致错误的原因是什么?

Max*_*axU 6

有一个更简单的方法:

>>> df.groupBy("product").agg({"Sales":"count"}).show()
+-------+------------+
|product|count(Sales)|
+-------+------------+
|  phone|           1|
|     tv|           2|
+-------+------------+
Run Code Online (Sandbox Code Playgroud)


Ram*_*jan 6

您的第一次尝试是在进行聚合之前过滤掉列null中的行。Sales因此它会给你正确的结果。

但是用第二个代码

df.groupBy('product') \
    .agg((F.count(F.col("Sales").isNotNull()).alias("sales_count"))).show()
Run Code Online (Sandbox Code Playgroud)

您还没有对整个数据集filtered进行处理。aggregation如果你仔细分析F.col("Sales").isNotNull()会给你布尔列 ietruefalse。因此F.count(F.col("Sales").isNotNull()) ,只需计算分组数据集中的布尔值,如果您创建如下所示的新列,这一点就会很明显。

df.withColumn("isNotNull", F.col("Sales").isNotNull()).show()
Run Code Online (Sandbox Code Playgroud)

这会给你

df.groupBy('product') \
    .agg((F.count(F.col("Sales").isNotNull()).alias("sales_count"))).show()
Run Code Online (Sandbox Code Playgroud)

因此,您第二次尝试的计数是正确的。

对于您的第三次尝试,.count()是一个不能在聚合转换中使用的操作。只能使用返回 dataType 的函数,它们可以是内置函数、UDF 或您自己的函数。Column.agg()