Собирать в массив только ненулевые столбцы каждой строки - PullRequest
0 голосов
/ 07 ноября 2019

Сложность в том, что я стараюсь избегать UDF как можно больше.

У меня есть набор данных "wordsDS", который содержит много нулевых значений:

+------+------+------+------+
|word_0|word_1|word_2|word_3|
+------+------+------+------+
|     a|     b|  null|     d|
|  null|     f|     m|  null|
|  null|  null|     d|  null|
+--------------+------+-----|

Мне нужно собрать все столбцы для каждой строки в массиве . Я не знаю количество столбцов заранее, поэтому я использую метод columns ().

groupedQueries = wordsDS.withColumn("collected",
      functions.array(Arrays.stream(wordsDS.columns())
               .map(functions::col).toArray(Column[]::new)));;

Но при таком подходе создаются пустые элементы :

+--------------------+
|           collected|
+--------------------+
|           [a, b,,d]|
|          [, f, m,,]|
|            [,, d,,]|
+--------------------+

Вместо этого мне нужен следующий результат:

+--------------------+
|           collected|
+--------------------+
|           [a, b, d]|
|              [f, m]|
|                 [d]|
+--------------------+

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

  1. Результирующий массив не содержит пустых элементов.
  2. Не знаю количество столбцов заранее.

Я также придерживался подхода фильтрацииСтолбец набора данных для пустых значений, но не может предложить ничего другого, кроме UDF. Я стараюсь избегать UDF, чтобы не снижать производительность, , если кто-нибудь может предложить способ фильтрации столбца "собранных" набора данных для пустых значений с минимальными издержками , это было бы очень полезно.

Ответы [ 2 ]

0 голосов
/ 08 ноября 2019

spark <2.0 вы можете использовать def для удаления null </p>

scala> var df = Seq(("a",  "b",  "null",  "d"),("null",  "f",  "m",  "null"),("null",  "null",  "d",  "null")).toDF("word_0","word_1","word_2","word_3")


scala> def arrayNullFilter = udf((arr: Seq[String]) => arr.filter(x=>x != "null"))

scala> df.select(array('*).as('all)).withColumn("test",arrayNullFilter(col("all"))).show
+--------------------+---------+
|                 all|     test|
+--------------------+---------+
|     [a, b, null, d]|[a, b, d]|
|  [null, f, m, null]|   [f, m]|
|[null, null, d, n...|      [d]|
+--------------------+---------+

надеюсь, это вам поможет.

0 голосов
/ 07 ноября 2019

вы можете использовать array("*"), чтобы получить все элементы в 1 массив, затем использовать array_except (требуется Spark 2.4+), чтобы отфильтровать нули:

df
  .select(array_except(array("*"),array(lit(null))).as("collected"))
  .show()

дает

+---------+
|collected|
+---------+
|[a, b, d]|
|   [f, m]|
|      [d]|
+---------+
...