scala spark-根据可变日期匹配数据框

时间:2018-12-28 18:54:07

标签: scala apache-spark

我正在尝试根据可变日期窗口来匹配两个数据框。我不仅仅是在尝试通过代码实现完全匹配,而且是在可变的日期窗口内获取所有可能的候选对象。

我能够通过代码获得日期的完全匹配。

但是我想找出记录是否仍然可以匹配,因为它们可能离双方都有几天,但仍然足够合理。

我试图在火花中寻找类似于python pd.to_timedelta('1 day')的东西来添加到过滤器中,但是可惜没有走运。

这是我当前的代码,该代码与 ID 列上的数据框匹配,然后运行过滤器以确保第二个数据框中的 from_date 第一个数据框的开始日期和结束日期

我不需要的是确切的日期匹配,但是如果记录在实际日期的一两天(两边)之间,则能够进行匹配。

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder().getOrCreate()

val df1 = spark.read.option("header","true")
               .option("inferSchema","true").csv("../data/df1.csv")

val df2 = spark.read.option("header","true")
               .option("inferSchema","true")
               .csv("../data/df2.csv")

val df = df2.join(df1,
                      (df1("ID") === df2("ID")) &&
                      (df2("from_date") >= df1("start_date")) &&
                      (df2("from_date") <= df1("end_date")),"left")
            .select(df1("ID"), df1("start_date"), df1("end_date"), 
                                                  $"from_date", $"to_date")

df.coalesce(1).write.format("com.databricks.spark.csv")
  .option("header", "true").save("../mydata.csv")

基本上,我希望能够编辑此日期窗口以增加或减少实际匹配的数据。

非常感谢您的投入。我是Spark / scala的新手,但必须说到目前为止,我一直很喜欢它……比python更快(更干净)!

欢呼

2 个答案:

答案 0 :(得分:2)

您可以在XMLSchema-instance条件下将date_adddate_sub应用于start_date/end_date,如下所示:

join

答案 1 :(得分:1)

您还可以使用datediff()函数获得相同的结果。检查一下:

scala> val df1 = Seq((1,  "2018-12-01", "2018-12-05"),(2,  "2018-12-01", "2018-12-06"),(3,  "2018-12-01", "2018-12-07")).toDF("ID", "start_date", "end_date").withColumn("start_date",'start_date.cast("date")).withColumn("end_date",'end_date.cast("date"))
df1: org.apache.spark.sql.DataFrame = [ID: int, start_date: date ... 1 more field]

scala> val df2 = Seq((1,  "2018-11-30"), (2,  "2018-12-08"),(3,  "2018-12-08")).toDF("ID", "from_date").withColumn("from_date",'from_date.cast("date"))
df2: org.apache.spark.sql.DataFrame = [ID: int, from_date: date]

scala> val delta = 1;
delta: Int = 1

scala> df2.join(df1,df1("ID") === df2("ID") && datediff('from_date,'start_date) >= -delta && datediff('from_date,'end_date)<=delta, "leftOuter").show(false)
+---+----------+----+----------+----------+
|ID |from_date |ID  |start_date|end_date  |
+---+----------+----+----------+----------+
|1  |2018-11-30|1   |2018-12-01|2018-12-05|
|2  |2018-12-08|null|null      |null      |
|3  |2018-12-08|3   |2018-12-01|2018-12-07|
+---+----------+----+----------+----------+


scala>