在Spark

时间:2018-02-09 13:49:15

标签: scala apache-spark apache-spark-sql

我的数据框就像这样

id  value  date    
1   100    2017 
1   null   2016 
1   20     2015 
1   100    2014

我想获得最近的先前值,但忽略null

id  value  date   recent value
1   100    2017    20
1   null   2016    20
1   20     2015   100
1   100    2014   null

使用引导窗口功能时是否有任何方法可以忽略空值。

2 个答案:

答案 0 :(得分:3)

  

在Spark

中使用主窗口功能时是否可以忽略空值

不是。

  

我想获得最近的值,但忽略null

只需将last(或first)与ignoreNulls

一起使用即可
  

def last(columnName: String, ignoreNulls: Boolean): Column

     

聚合函数:返回组中列的最后一个值。

     

默认情况下,该函数返回它看到的最后一个值。当ignoreNulls设置为true时,它将返回它看到的最后一个非null值。如果所有值都为null,则返回null。

import org.apache.spark.sql.functions._
import org.apache.spark.sql.expressions._

val df = Seq(
  (1, Some(100), 2017), (1, None, 2016), (1, Some(20), 2015), 
  (1, Some(100), 2014)
).toDF("id", "value", "date")

df.withColumn(
  "last_value",
   last("value", true).over(Window.partitionBy("id").orderBy("date"))
).show

+---+-----+----+----------+                                                     
| id|value|date|last_value|
+---+-----+----+----------+
|  1|  100|2014|       100|
|  1|   20|2015|        20|
|  1| null|2016|        20|
|  1|  100|2017|       100|
+---+-----+----+----------+

答案 1 :(得分:0)

您可以分两步完成:

  1. 创建一个包含非空值的表
  2. 加入原表
import org.apache.spark.sql.functions._
import org.apache.spark.sql.expressions._

val df = Seq(
  (1, Some(100), 2017),
  (1, None, 2016),
  (1, Some(20), 2015),
  (1, Some(100), 2014)
).toDF("id", "value", "date")

// Step 1
val filledDf = df
  .where($"value".isNotNull)
  .withColumnRenamed("value", "recent_value")

// Step 2
val window: WindowSpec = Window.partitionBy("l.id", "l.date").orderBy($"r.date".desc)

val finalDf = df.as("l")
  .join(filledDf.as("r"), $"l.id" === $"r.id" && $"l.date" > $"r.date", "left")
  .withColumn("rn", row_number().over(window))
  .where($"rn" === 1)
  .select("l.id", "l.date", "value", "recent_value")

finalDf.orderBy($"date".desc).show

+---+----+-----+------------+
| id|date|value|recent_value|
+---+----+-----+------------+
|  1|2017|  100|          20|
|  1|2016| null|          20|
|  1|2015|   20|         100|
|  1|2014|  100|        null|
+---+----+-----+------------+