Pyspark - 计算每个数据框列中的空值数量

5

我有一个包含许多列的数据框。我的目标是生成一个数据框,其中列名及其该列中空值的数量被列出。

例如:

+-------------+-------------+
| Column_Name | NULL_Values |
+-------------+-------------+
|  Column_1   |      15     |
|  Column_2   |      56     |
|  Column_3   |      18     |
|     ...     |     ...     |
+-------------+-------------+

我已成功获取了一个列的空值数量,代码如下:

df.agg(F.count(F.when(F.isnull(c), c)).alias('NULL_Count'))

c是数据框中的一列。然而,它不显示列的名称。输出如下:

+------------+
| NULL_Count |
+------------+
|     15     |
+------------+

有什么想法吗?

2个回答

17
你可以使用列表推导式来循环遍历agg中的所有列,并使用alias来重命名输出列:
import pyspark.sql.functions as F

df_agg = df.agg(*[F.count(F.when(F.isnull(c), c)).alias(c) for c in df.columns])

然而,这将会返回如下所示的一行结果:

df_agg.show()
#+--------+--------+--------+
#|Column_1|Column_2|Column_3|
#+--------+--------+--------+
#|      15|      56|      18|
#+--------+--------+--------+

如果您希望结果只在一列中显示,可以使用functools.reduce将来自df_agg的每个列进行联合,具体方法如下:

from functools import reduce
df_agg_col = reduce(
    lambda a, b: a.union(b),
    (
        df_agg.select(F.lit(c).alias("Column_Name"), F.col(c).alias("NULL_Count")) 
        for c in df_agg.columns
    )
)
df_agg_col.show()
#+-----------+----------+
#|Column_Name|NULL_Count|
#+-----------+----------+
#|   Column_1|        15|
#|   Column_2|        56|
#|   Column_3|        18|
#+-----------+----------+

或者您可以跳过创建df_agg的中间步骤,直接执行:

df_agg_col = reduce(
    lambda a, b: a.union(b),
    (
        df.agg(
            F.count(F.when(F.isnull(c), c)).alias('NULL_Count')
        ).select(F.lit(c).alias("Column_Name"), "NULL_Count")
        for c in df.columns
    )
)

完美运行,谢谢!您能解释一下在第一个聚合函数中星号的作用吗? - LEJ
@LEJ * 是用于进行参数解包的。该语法可以将列表的内容“解包”以便作为函数参数传递。 - pault

0

Scala可能的替代方案

case class Test(id:Int, weight:Option[Int], age:Int, gender: Option[String])

val df1 = Seq(Test(1, Some(100), 23, Some("Male")), Test(2, None, 25, None), Test(3, None, 33, Some("Female"))).toDF()

df1.show()

+---+------+---+------+
| id|weight|age|gender|
+---+------+---+------+
|  1|   100| 23|  Male|
|  2|  null| 25|  null|
|  3|  null| 33|Female|
+---+------+---+------+

val s = df1.columns.map(c => sum(col(c).isNull.cast("integer")).alias(c))

val df2 = df1.agg(s.head, s.tail:_*)

val t = df2.columns.map(c => df2.select(lit(c).alias("col_name"), col(c).alias("null_count")))

val df_agg_col = t.reduce((df1, df2) => df1.union(df2))

df_agg_col.show()

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