Как проверить, не равны ли значения нескольких столбцов строки null, а затем добавить результирующий столбец true / false в Spark Scala

#scala #apache-spark

#scala #apache-spark

Вопрос:

Привет, как дела? Вот мои два фрейма данных:

   val id_df = Seq(("1","gender"),("2","city"),("3","state"),("4","age")).toDF("id","type")

  val main_df = Seq(("male","los angeles","null"),("female","new york","new york")).toDF("1","2","3")
  

Вот как они выглядят в табличной форме:

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

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

и это то, что я хотел бы, чтобы результирующий фрейм данных выглядел так:

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

Я хочу проверить все идентификаторы в id_df, если они существуют в столбцах main_df, а затем проверить, все ли значения идентификаторов для этой строки не равны null. Если все они не равны null, то мы помещаем «true» в столбец «соответствует условию» для этой строки, в противном случае мы помещаем «false». Обратите внимание, что идентификационный номер 4 для age отсутствует в столбцах main_df, поэтому мы просто игнорируем его.

Как мне это сделать?

Большое спасибо и хорошего дня.

Ответ №1:

Позвольте мне начать с двух коротких наблюдений:

  1. Я считаю, что было бы безопаснее избегать именования наших столбцов одиночными числами. Подумайте о случае, когда нам нужно вычислить выражение 1 is not null . Здесь неоднозначно, имеем ли мы в виду column 1 или value 1 само.
  2. Насколько мне известно, хранить и обрабатывать целевые столбцы через фрейм данных неэффективно. Это создало бы накладные расходы, которых можно легко избежать, используя единую коллекцию scala, т.е. Seq, Array, Set и т. Д.

И вот решение вашей проблемы:

 import org.apache.spark.sql.functions.col

val id_df = Seq(
  ("c1","gender"),
  ("c2","city"),
  ("c3","state"),
  ("c4","age")
).toDF("id","type")

val main_df = Seq(
    ("male", "los angeles", null),
    ("female", "new york", "new york"),
    ("trans", null, "new york")
).toDF("c1","c2","c3")

val targetCols = id_df.collect()
                      .map{_.getString(0)} //get id
                      .toSet //convert current sequence to a set (required for the intersection)
                      .intersect(main_df.columns.toSet) //get common columns with main_df
                      .map(col(_).isNotNull) //convert c1,..cN to col(c[i]).isNotNull
                      .reduce(_ amp;amp; _) // apply the AND operator between items

// (((c1 IS NOT NULL) AND (c2 IS NOT NULL)) AND (c3 IS NOT NULL))

main_df.withColumn("meets_conditions", targetCols).show(false)

//  ------ ----------- -------- ---------------- 
// |c1    |c2         |c3      |meets_conditions|
//  ------ ----------- -------- ---------------- 
// |male  |los angeles|null    |false           |
// |female|new york   |new york|true            |
// |trans |null       |new york|false           |
//  ------ ----------- -------- ---------------- 
  

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

1. позвольте мне повторить вопрос, потому что я не совсем понимаю ваш ответ