我的数据框如下,有三列
id|visit_class|in_date
+--+-----------+--------
|1|Non Hf |24-SEP-2017
|1|Non Hf |23-SEP-2017
|1|Hf |27-SEP-2017
|1|Non Hf |28-SEP-2017
|2|Non Hf |24-SEP-2017
|2|Hf |25-SEP-2017
我想在id上对这个数据框进行分组,然后在indate列上对这个分组数据进行排序,并且只想要在首次出现HF之后出现的那些行。输出如下。对于id = 1,前2行将下降,对于id = 2,前1行将下降。
id|visit_class|in_date
+--+-----------+--------
|1|Hf |27-SEP-2017
|1|Non Hf |28-SEP-2017
|2|Hf |25-SEP-2017
我将如何在Spark和Scala中实现这一目标。
答案 0 :(得分:4)
步骤:
1)创建WindowSpec,按date
排序,按id
分区:
2)创建一个累计和,以指示Hf
是否已出现,然后根据条件进行过滤:
import org.apache.spark.sql.expressions.Window
val w = Window.partitionBy("id").orderBy(to_date($"in_date", "dd-MMM-yyyy"))
(df.withColumn("rn", sum(when($"visit_class" === "Hf", 1).otherwise(0)).over(w))
.filter($"rn" >= 1).drop("rn").show)
+---+-----------+-----------+
| id|visit_class| in_date|
+---+-----------+-----------+
| 1| Hf|27-SEP-2017|
| 1| Non Hf|28-SEP-2017|
| 2| Hf|25-SEP-2017|
+---+-----------+-----------+
使用spark 2.2.0,带有格式签名的to_date
是2.2.0中的新函数
如果你正在使用spark< 2.2.0,您可以使用unix_timestamp
代替to_date
:
val w = Window.partitionBy("id").orderBy(unix_timestamp($"in_date", "dd-MMM-yyyy"))