Функции Spark Window: возможно ли получить другие значения непосредственно из строки, найденной с помощью первой / последней функций? - PullRequest
0 голосов
/ 08 января 2019

В Spark можно получить первое ненулевое значение после текущего вхождения для столбца в окне:

val window = Window
  .orderBy("id")

val df = Seq(
  (0, "Bob", Some(123)),
  (1, "Jack", None),
  (2, "Brian", None),
  (3, "John", Some(456)),
  (4, "Edgar", None)
).toDF("id", "name", "value")

df
  .withColumn("firstNonNullValueAfterRow", first("value", true)
    .over(window.rowsBetween(Window.currentRow, Window.unboundedFollowing)))
  .show()

Выход:

+---+-----+-----+-------------------------+
| id| name|value|firstNonNullValueAfterRow|
+---+-----+-----+-------------------------+
|  0|  Bob|  123|                      123|
|  1| Jack| null|                      456|
|  2|Brian| null|                      456|
|  3| John|  456|                      456|
|  4|Edgar| null|                     null|
+---+-----+-----+-------------------------+

Вопрос: возможно ли получить другое значение из строки, которую мы получили, используя .first (...)? Я хотел бы получить имя человека, который отображается на первое ненулевое значение после этой записи:

+---+-----+-----+-------------------------+-------------------------+
| id| name|value|firstNonNullValueAfterRow|nameOfThatPerson         |
+---+-----+-----+-------------------------+-------------------------+
|  0|  Bob|  123|                      123|                      Bob|
|  1| Jack| null|                      456|                     John|
|  2|Brian| null|                      456|                     John|
|  3| John|  456|                      456|                     John|
|  4|Edgar| null|                     null|                     null|
+---+-----+-----+-------------------------+-------------------------+

Это возможно с некоторыми хитростями, но я хотел бы знать, есть ли способ сделать это с помощью оконных функций Spark. Временное решение:

val idAndNameDF = df
  .select("id", "name")
  .withColumnRenamed("id", "id2")
  .withColumnRenamed("name", "nameOfThatPerson")

df
  .withColumn("idOfFirstNotNullValue", when(col("value").isNotNull, col("id")))
  .withColumn("firstNonNullIdAfterRow", first("idOfFirstNotNullValue", true)
    .over(window.rowsBetween(Window.currentRow, Window.unboundedFollowing)))
  .join(idAndNameDF, col("firstNonNullIdAfterRow") === col("id2"),"left")
  .show()

Результат обхода:

+---+-----+-----+---------------------+----------------------+----+----------------+
| id| name|value|idOfFirstNotNullValue|firstNonNullIdAfterRow| id2|nameOfThatPerson|
+---+-----+-----+---------------------+----------------------+----+----------------+
|  0|  Bob|  123|                    0|                     0|   0|             Bob|
|  1| Jack| null|                 null|                     3|   3|            John|
|  2|Brian| null|                 null|                     3|   3|            John|
|  3| John|  456|                    3|                     3|   3|            John|
|  4|Edgar| null|                 null|                  null|null|            null|
+---+-----+-----+---------------------+----------------------+----+----------------+

1 Ответ

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

Да и нет. Нет, это не так, если вы имеете в виду, что оно должно быть частью одного и того же предложения Window или общего предложения. Да, если вы делаете что-то лишнее.

То есть, ваш обходной путь правильный.

Это два разных аспекта:

  • Найти первое «будущее» ненулевое вхождение
  • А затем найдите связанные данные для этого случая.

Это что-то вроде разума. Вы должны увидеть это как ситуацию с подзапросом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...