有没有办法从特定行的列中获取值并将其放入下一行?

时间:2019-05-22 12:55:37

标签: java apache-spark

我的数据如下所示

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
...

我正在Java中使用Apache Spark。

之后,将使用groupby和ivot处理数据。

我在想类似的东西

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);

我不知道这是否可行。

帮助表示感谢,非常感谢!

2 个答案:

答案 0 :(得分:2)

可以创建具有传感器ID范围的数据框,然后将其加入原始数据框:

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

答案 1 :(得分:1)

在有序窗口上使用lastignoreNulls进行聚合会达到目的

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设置,但应该易于翻译