Есть ли способ получить значение из столбца в определенной строке и поместить его в следующую строку?

У меня есть данные, которые выглядят следующим образом

ID    Sensor          No
1     specificSensor  1
2     1234            null 
3     1234            null
4     specificSensor  2
5     2345            null
6     2345            null
7

... 

Мне нужен выходной формат, подобный этому

ID    Sensor          No
1     specificSensor  1
2     1234            1 
3     1234            1
4     specificSensor  2
5     2345            2
6     2345            2
7
...

Я использую Apache Spark в Java.

после этого данные обрабатываются с помощью groupby и pivot.

Я думаю о чем-то вроде

df.withColumn("No", functions.when(df.col("Sensor").equalTo("specificSensor"), functions.monotonically_increasing_id())
//this works as I need it
.otherwise(WHEN NULL THEN VALUE ABOVE);

Я не знаю, возможно ли это в каком-то смысле.

Помощь приветствуется, большое спасибо!

Если бы у вас был ключ группировки, это было бы легко использовать с помощью WindowSpec, но я не вижу этого в предоставленных вами данных.

Michel Lemay 22.05.2019 14:59

Я группирую с «Нет» и поворачиваю таблицу. то, что я также пробовал, было functions.lag(), но он всегда вылетает, говоря Cannot evaluate expression: lag(input[3, bigint, true], 1, null)

UNoWhoIam 22.05.2019 15:21
Основы программирования на Java
Основы программирования на Java
Java - это высокоуровневый объектно-ориентированный язык программирования, основанный на классах.
Концепции JavaScript, которые вы должны знать как JS программист!
Концепции JavaScript, которые вы должны знать как JS программист!
JavaScript (Js) - это язык программирования, объединяющий HTML и CSS с одной из основных технологий Всемирной паутины. Более 97% веб-сайтов используют...
0
2
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Фрейм данных с диапазонами идентификаторов датчиков можно создать, а затем соединить с исходным фреймом данных:

val df = Seq((1, "specificSensor", Some(1)),
  (2, "1234", None),
  (3, "1234", None),
  (4, "specificSensor", Some(2)),
  (5, "2345", None),
  (6, "2345", None))
  .toDF("ID", "Sensor", "No")

val idWindow = Window.orderBy("ID")
val sensorsRange = df
    .where($"Sensor" === "specificSensor")
    .withColumn("nextId", coalesce(lead($"id", 1).over(idWindow), lit(Long.MaxValue)))

sensorsRange.show(false)

val joinColumn = $"d.ID" > $"s.id" && $"d.ID" < $"s.nextId"
val result =
  df.alias("d")
    .join(sensorsRange.alias("s"), joinColumn, "left")
    .select($"d.ID", $"d.Sensor", coalesce($"d.No", $"s.No").alias("No"))

Выход:

+---+--------------+---+-------------------+
|ID |Sensor        |No |nextId             |
+---+--------------+---+-------------------+
|1  |specificSensor|1  |4                  |
|4  |specificSensor|2  |9223372036854775807|
+---+--------------+---+-------------------+


+---+--------------+---+
|ID |Sensor        |No |
+---+--------------+---+
|1  |specificSensor|1  |
|2  |1234          |1  |
|3  |1234          |1  |
|4  |specificSensor|2  |
|5  |2345          |2  |
|6  |2345          |2  |
+---+--------------+---+

спасибо за ответ! пытаюсь построить это в java, но я продвигаюсь очень медленно... есть ли другой способ переформатировать? Я думал о следующем: в то время как значение eq null делать: копировать сверху

UNoWhoIam 22.05.2019 17:11

В моем подходе ненулевые значения берутся с датчиков. В подходе "ollik1" используется чисто оконная функция, аналогичная "пока". Единственная проблема - оконная функция без разделов может иметь снижение производительности.

pasha701 23.05.2019 10:38
Ответ принят как подходящий

Использование агрегации last с ignoreNulls по упорядоченному окну помогает

df.select(
    $"ID",
    $"Sensor",
    last($"No", ignoreNulls = true) over Window.orderBy($"ID") as "No")
  .show()

Выход:

+---+--------------+---+
| ID|        Sensor| No|
+---+--------------+---+
|  1|specificSensor|  1|
|  2|          1234|  1|
|  3|          1234|  1|
|  4|specificSensor|  2|
|  5|          2345|  2|
|  6|          2345|  2|
+---+--------------+---+

P.S. У меня сейчас нет рабочей установки Java, но ее легко перевести.

это очень хорошее и простое решение, которое работало на ходу! Булево значение JavaCode ignoreNulls = true; Набор данных <Row> ds1 = ds .withColumn("Нет", functions.last("Нет", ignoreNulls).over(Window.orderBy(ds.col("ID").as("Нет")))));

UNoWhoIam 23.05.2019 14:21

Другие вопросы по теме