Выберите все ненулевые имена столбцов в строке в искре - PullRequest
1 голос
/ 18 февраля 2020

Предположим, у меня есть кадр данных, который выглядит следующим образом:

+-----+-----+-----+-----+
|  A  |  B  |  C  |  D  |
+-----+-----+-----+-----+
|  Y  |null |  Y  |null |
|null |  N  |  N  |null |
|  N  |  Y  |null |  N  |
+-----+-----+-----+-----+

Я хочу добавить новый столбец, который представляет собой объединение имен всех ненулевых столбцов для каждой строки.

Итак, для приведенного выше примера добавился бы новый столбец

+--------+
|non-null|
+--------+
| A, C   |
| B, C   |
| A, B, D|
+--------+

Есть ли простой способ сделать это? Я пытался найти анти-коалесценцию, что-бы, если не ноль, использовать предоставленное имя. Например, если было слияние:

df.withColumn("non-null", antiCoalesce("A", "A,") + antiCoalesce("B", "B,") + antiCoalesce("C", "C,") + antiCoalesce("D", "D"))

Увы, такой функции нет, но она демонстрирует то, что я ищу.

Ответы [ 3 ]

1 голос
/ 18 февраля 2020

А как насчет этого подхода? Вы можете concat_ws с новыми столбцами, которые содержат имя столбца, когда оно не равно нулю.

val df = Seq(("Y", null, "Y", null),
             (null, "N", "N", null),
             ("N", "Y", null, "N")).toDF("A", "B", "C", "D")

val columns = df.columns
columns.foldLeft(df) {(df, name) => df.withColumn(name + "2", when(!col(name).isNull, lit(name)))}
  .withColumn("non-null", concat_ws(",", columns.map(name => col(name + "2")): _*))
  .drop(columns.map(name => name + "2"): _*)
  .show(false)

Тогда

+----+----+----+----+--------+
|A   |B   |C   |D   |non-null|
+----+----+----+----+--------+
|Y   |null|Y   |null|A,C     |
|null|N   |N   |null|B,C     |
|N   |Y   |null|N   |A,B,D   |
+----+----+----+----+--------+
1 голос
/ 18 февраля 2020

Используя Spark 2.4+, вы можете сделать что-то вроде этого:

val nonNullColsExpr = df.columns.map(c => when(col(c).isNotNull, lit(c)))

df.withColumn("non_null", array(nonNullColsExpr:_*))
  .withColumn("non_null", expr("array_join(non_null, ',')"))
  .show()

//+----+----+----+----+--------+
//|   A|   B|   C|   D|non_null|
//+----+----+----+----+--------+
//|   Y|null|   Y|null|     A,C|
//|null|   N|   N|null|     B,C|
//|   N|   Y|null|   N|   A,B,D|
//+----+----+----+----+--------+

Сначала мы создадим столбец массива, содержащий имена столбцов, которые удовлетворяют условию isNotNull, и те, которые не удовлетворяют, будут обнулены. Затем соедините элементы с помощью array_join, используя разделитель , (array_join фильтрует нулевые значения при объединении элементов).

0 голосов
/ 18 февраля 2020

В SQL вы можете express, используя concat_ws():

select concat_ws(',', 
                 (case when A is not null then 'A' end),
                 (case when B is not null then 'B' end),
                 (case when C is not null then 'C' end),
                 (case when D is not null then 'D' end)
                )
...