用先前的字段值填充DataFrame中的空白字段

时间:2019-03-19 18:39:02

标签: scala apache-spark

我正在使用Scala和Spark,并且在Scala编程方面相对较新,所以也许我的问题有一个简单的解决方案。

我有一个DataFrame可以保存有关某些促销中活动和停用客户端的信息。该DataFrame会显示客户ID,他/她采取的操作(他可以随时激活或停用促销)以及他/她采取此操作的日期。这是该格式的示例:

DataFrame如何工作的示例
Example of how the DataFrame works

我想每天监视活跃的客户,并希望了解这个数字在一天中的变化情况,但是我无法编写类似这样的代码。

我的想法是使两个数据框交叉连接。一个只有客户端ID,另一个只有日期,因此我将拥有与所有客户端ID相关的所有日期,并且我只需要在每个日期中查看客户端状态(如果客户端处于活动状态或非活动状态) 。因此,在此之后,我将这些新数据框与关联了客户端ID和事件的数据框左连接,但是结果是很多日期的状态为“空”,我不知道如何用它填充正确的状态。这是示例:

最终DataFrame的示例
Example of the final DataFrame

我已经尝试使用lag函数,但是它不能解决我的问题。有人有什么想法可以帮助我吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

由于Spark SQL对带有<,<=>,> =的相关子查询的限制,因此操作成本稍高。

从第二个带有NULL的数据帧开始,并假设有足够大的系统和可管理的数据量:

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

// My sample input
val df  = Seq( 
  (1,"2018-03-12", "activate"),
  (1,"2018-03-13", null),
  (1,"2018-03-14", null),
  (1,"2018-03-15", "deactivate"),
  (1,"2018-03-16", null),
  (1,"2018-03-17", null),
  (1,"2018-03-18", "activate"), 
  (2,"2018-03-13", "activate"), 
  (2,"2018-03-14", "deactivate"), 
  (2,"2018-03-15", "activate") 
 ).toDF("ID", "dt", "act")
//df.show(false)

val w = Window.partitionBy("ID").orderBy(col("dt").asc)
val df2 = df.withColumn("rank", dense_rank().over(w)).select("ID", "dt","act", "rank") //.where("rank == 1")
//df2.show(false)

val df3 = df2.filter($"act".isNull)
//df3.show(false)

val df4 = df2.filter(!($"act".isNull)).toDF("ID2", "dt2", "act2", "rank2")
//df4.show(false)

val df5 = df3.join(df4, (df3("ID") === df4("ID2")) && (df4("rank2") < df3("rank")),"inner") 
//df5.show(false)

val w2 = Window.partitionBy("ID", "rank").orderBy(col("rank2").desc)
val df6 = df5.withColumn("rank_final", dense_rank().over(w2)).where("rank_final == 1").select("ID", "dt","act2").toDF("ID", "dt", "act") 
//df6.show

val df7 = df.filter(!($"act".isNull))

val dfFinal = df6.union(df7)
dfFinal.show(false)

返回:

+---+----------+----------+
|ID |dt        |act       |
+---+----------+----------+
|1  |2018-03-13|activate  |
|1  |2018-03-14|activate  |
|1  |2018-03-16|deactivate|
|1  |2018-03-17|deactivate|
|1  |2018-03-12|activate  |
|1  |2018-03-15|deactivate|
|1  |2018-03-18|activate  |
|2  |2018-03-13|activate  |
|2  |2018-03-14|deactivate|
|2  |2018-03-15|activate  |
+---+----------+----------+

我一步一步地解决了这个问题,但是没有那么明显。