【问题标题】:Find out the closest value PySpark找出最接近的值 PySpark
【发布时间】:2021-11-16 15:01:20
【问题描述】:

我有一个包含以下列的数据框

'CUSTOMER_ID','ORDERED_TIME','ORDER_ID'

这里,ORDERED_TIME 是指示下订单时间的时间戳字段,CUSTOMER_ID 是客户 ID(整数),ORDER_ID 是订单 ID(整数)

现在,从这个数据框中,对于 2021 年 1 月到 2021 年 3 月 月份下的每个订单,我需要找出上一个订单的时间 就在之前 ORDERED_TIME。我们称这个专栏为PREV_ORDER_TIME

数据框包含一直到 2019 年的订单数据。但是,我只计算了 1 月至 3 月之间所有订单的 PREV_ORDER_TIME。如果订单没有PREV_ORDER_TIME订单,我想显示null

我的最终预期输出类似于['CUSTOMER_ID','ORDERED_TIME','ORDER_ID','PREV_ORDER_TIME']

据我了解,对于这3个月的一些订单,之前的订单可以在这3个月内,但对于其他一些订单,很可能在这个窗口之前。

我不确定如何处理这个问题。我觉得我可能需要使用一些二进制搜索来找到最接近的日期,但我不确定如何使这项工作仅适用于 1 月到 3 月的订单,尽管我的数据集包含早在此之前的订单。

【问题讨论】:

    标签: python dataframe apache-spark pyspark


    【解决方案1】:

    您可以在window 上使用lag 函数,如下所示:

    from pyspark.sql import Window
    from pyspark.sql import functions as F
    
    window = Window().partitionBy("CUSTOMER_ID").orderBy('ORDERED_TIME')
    
    dataframe.withColumn('PREV_ORDER_TIME', F.lag('ORDERED_TIME').over(window))
    

    如果没有先前的订单,列PREV_ORDER_TIME 将是null

    如果您只想为 2021-01-01 和 2021-03-31 之间的日期计算此 PREV_ORDER_TIME 列,则可以添加 when 子句,如下所示:

    from datetime import datetime
    
    from pyspark.sql import Window
    from pyspark.sql import functions as F
    
    window = Window().partitionBy("CUSTOMER_ID").orderBy('ORDERED_TIME')
    
    dataframe.withColumn(
      'PREV_ORDER_TIME', 
      F.when(
        (F.col('ORDERED_TIME') < datetime(2021, 4, 1)) & (F.col('ORDERED_TIME') >= datetime(2021, 1, 1)),
        F.lag('ORDERED_TIME').over(window)
      )
    )
    

    对于日期不在 2021-01-01 和 2021-03-31 之间的所有订单,PREV_ORDER_TIME 列将是 null

    所以如果你有以下输入数据框:

    +-----------+--------+-------------------+
    |CUSTOMER_ID|ORDER_ID|ORDERED_TIME       |
    +-----------+--------+-------------------+
    |1          |21      |2019-12-15 10:20:30|
    |1          |22      |2020-12-16 11:21:31|
    |1          |23      |2021-01-17 12:22:32|
    |2          |24      |2021-01-18 13:23:33|
    |2          |25      |2021-02-19 14:24:34|
    |2          |26      |2021-03-20 15:25:35|
    +-----------+--------+-------------------+
    

    你会得到以下输出:

    +-----------+--------+-------------------+-------------------+
    |CUSTOMER_ID|ORDER_ID|ORDERED_TIME       |PREV_ORDER_TIME    |
    +-----------+--------+-------------------+-------------------+
    |1          |21      |2019-12-15 10:20:30|null               |
    |1          |22      |2020-12-16 11:21:31|null               |
    |1          |23      |2021-01-17 12:22:32|2020-12-16 11:21:31|
    |2          |24      |2021-01-18 13:23:33|null               |
    |2          |25      |2021-02-19 14:24:34|2021-01-18 13:23:33|
    |2          |26      |2021-03-20 15:25:35|2021-02-19 14:24:34|
    +-----------+--------+-------------------+-------------------+
    

    【讨论】:

    • 谢谢,我今天学到了一些新东西。滞后和排序组合非常好。只是为了澄清一下,除了那些没有先前订单的订单,对于那些不在此窗口中的订单(例如,如果它是在 2020 年 12 月下达但仍有先前订单),即使对于那些,prev_order_time 也将为空,对吗?
    • @JiteshMalipeddi 是的,它将是null。我在答案中添加了一个示例来澄清这一点。
    • 仅供参考,使用 datetime.date(2021, 4, 1)) 而不是 datetime(2021, 4, 1) 为我工作
    猜你喜欢
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多