В 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|
+---+-----+-----+---------------------+----------------------+----+----------------+