如何基于第一个出现日期并基于每个id列的其他列创建数据框

问题描述 投票:1回答:1

我尝试创建一个具有以下条件的数据帧:我有多个ID,多列默认值(0或1)和一个startdate列。我想根据第一个startdate(default_date)和每个id获得一个带有出现默认值的数据帧。

原来的df看起来像这样:

+----+-----+-----+-----+-----------+
|id  |def_a|def_b|deb_c|date       |
+----+-----+-----+-----+-----------+
|  01|    1|    0|    1| 2019-01-31|
|  02|    1|    1|    0| 2018-12-31|
|  03|    1|    1|    1| 2018-10-31|
|  01|    1|    0|    1| 2018-09-30|
|  02|    1|    1|    0| 2018-08-31|
|  03|    1|    1|    0| 2018-07-31|
|  03|    1|    1|    1| 2019-05-31|

这就是我想要的方式:

+----+-----+-----+-----+-----------+
|id  |def_a|def_b|deb_c|date       |
+----+-----+-----+-----+-----------+
|  01|    1|    0|    1| 2018-09-30|
|  02|    1|    1|    0| 2018-08-31|
|  03|    1|    1|    1| 2018-07-31|

我试过以下代码:

val w = Window.partitionBy($"id").orderBy($"date".asc) 
val reult = join3.withColumn("rn", row_number.over(w)).where($"def_a" === 1 || $"def_b" === 1 ||$"def_c" === 1).filter($"rn" >= 1).drop("rn")

result.show

我将不胜感激任何帮助

scala apache-spark-sql
1个回答
1
投票

这应该适合你。首先将最小日期分配给原始df,然后使用df加入新df2。

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

val df = Seq(
(1,1,0,1,"2019-01-31"),
(2,1,1,0,"2018-12-31"),
(3,1,1,1,"2018-10-31"),
(1,1,0,1,"2018-09-30"),
(2,1,1,0,"2018-08-31"),
(3,1,1,0,"2018-07-31"),
(3,1,1,1,"2019-05-31"))
.toDF("id"  ,"def_a" , "def_b", "deb_c", "date")

val w = Window.partitionBy($"id").orderBy($"date".asc) 

val df2 = df.withColumn("date", $"date".cast("date"))
            .withColumn("min_date", min($"date").over(w))
            .select("id", "min_date")
            .distinct()

df.join(df2, df("id") === df2("id") && df("date") === df2("min_date"))
.select(df("*"))
.show

输出应该是:

+---+-----+-----+-----+----------+
| id|def_a|def_b|deb_c|      date|
+---+-----+-----+-----+----------+
|  1|    1|    0|    1|2018-09-30|
|  2|    1|    1|    0|2018-08-31|
|  3|    1|    1|    0|2018-07-31|
+---+-----+-----+-----+----------+

顺便说一句,我相信你对预期结果有一点误会。它是(3, 1, 1, 0, 2018-07-31)而不是(3, 1, 1, 1, 2018-07-31)

© www.soinside.com 2019 - 2024. All rights reserved.