如何根据某些条件从Spark数据框中获取几行

时间:2017-09-15 14:39:29

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

我的数据框如下,有三列

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中实现这一目标。

1 个答案:

答案 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"))