-2

我需要使用 Scala 对表执行一些完整性检查。

我的示例表是:

在此处输入图像描述

可以使用以下代码生成它:

val df = Seq(
    (1, "", "13-05-2020", Some("CSE")),
    (2, "PQR", "14022019", None),
    (3, "XYZ", "25-01-2018", Some(""))
).toDF("ID", "NAME", "Joining Date", "Branch")

现在,我想对所有列执行 Null Check 和 Date Check。我希望输出如下:

在此处输入图像描述

我能够生成这样的数据框:

在此处输入图像描述

请帮助我将数据填充到此 DF 中。

4

1 回答 1

1

据我了解,您想对数据框的所有列计算一些通用测试。

此外,您似乎认为空字符串""就像一个空值。因此,我将从用空值替换空字符串开始(仅适用于字符串类型的列)。

import org.apache.spark.sql.types.StringType
val df_with_nulls = df.select(df.schema.fields.map(c =>
         if(c.dataType == StringType)
             when(col(c.name) === "", null).otherwise(col(c.name)) as c.name
         else
             col(c.name)
) : _*)

然后,为了更清晰的代码,我将为您要执行的每个检查定义一个函数。如果它们不是您想要的,请随意调整它们:

val name = (c : String) => lit(c) as s"col_list"
val null_check =
    (c : String) => sum(col(c).isNull.cast("int")) > 0 as s"Null_check"
val date_pattern = "[0-9]{2}-?[0-9]{2}-?[0-9]{4}"
val date_check =
    (c : String) => sum(col(c) rlike date_pattern cast "int") > 0 as s"Date_Check"
val distinct_values = (c : String) => collect_set(col(c)) as "Distinct_Values"

最后,您可以以通用方式将所有这些应用于您的所有列,如下所示:

df_with_nulls
    .select(array(df.columns.map(c =>
            struct(name(c), date_check(c), null_check(c), distinct_values(c))
    ) : _*) as "a")
    .select(explode('a) as "s")
    .select("s.*")
    .show(false)

而产生你所期望的:

+------------+----------+----------+----------------------------------+
|col_list    |Date_Check|Null_check|Distinct_Values                   |
+------------+----------+----------+----------------------------------+
|ID          |false     |false     |[1, 2, 3]                         |
|NAME        |false     |true      |[PQR, XYZ]                        |
|Joining Date|true      |false     |[14022019, 13-05-2020, 25-01-2018]|
|Branch      |false     |true      |[CSE]                             |
+------------+----------+----------+----------------------------------+

我唯一的警告是不要在具有太多不同值的列上使用它。实际上,由于它们都聚合到一行,这将非常缓慢或更糟,导致 OOM 异常。

于 2020-10-13T08:26:47.447 回答