据我了解,您想对数据框的所有列计算一些通用测试。
此外,您似乎认为空字符串""
就像一个空值。因此,我将从用空值替换空字符串开始(仅适用于字符串类型的列)。
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 异常。