Хотите транспонировать столбцы в spark scala

#scala #apache-spark #sanity-check

#scala #apache-spark #проверка работоспособности

Вопрос:

У меня есть требование выполнить некоторые проверки работоспособности таблицы с использованием 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 и проверку даты для всех столбцов. И я хочу, чтобы результат был похож:

введите описание изображения здесь

Я смог сгенерировать фрейм данных следующим образом:

введите описание изображения здесь

Пожалуйста, помогите мне заполнить данные в этом DF.

Комментарии:

1. Можете ли вы поделиться кодом, который вы написали до сих пор (как вы генерируете данные, как вы создали этот окончательный df и что вы пытались заполнить)

Ответ №1:

Насколько я понимаю, вы хотите вычислить некоторые общие тесты для всех столбцов фрейма данных.

Также вы, кажется, считаете, что пустая строка "" похожа на нулевое значение. Поэтому я бы начал с замены пустых строк на значения null (только для столбцов типа string).

 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)
  

while выдает то, что вы ожидаете:

  ------------ ---------- ---------- ---------------------------------- 
|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]                             |
 ------------ ---------- ---------- ---------------------------------- 
  

Моим единственным предупреждением было бы не использовать это для столбца со слишком большим количеством различных значений. Действительно, поскольку все они объединены в одну строку, это будет очень медленно или хуже, вызовет исключение ООМ.