【问题标题】:How to do a count the number of previous occurence in Pyspark如何计算Pyspark中先前出现的次数
【发布时间】:2021-07-29 13:50:54
【问题描述】:

我有以下 pyspark 数据框。

cust_id apply_date
1 01-06-2014
1 01-07-2014
1 01-04-2018
1 01-07-2018
2 01-04-2015
2 01-05-2015
2 01-06-2015
2 01-09-2015

我想计算客户在过去 6 个月内提出的申请数量 不包括当前的应用程序。

所以输出应该是:

cust_id apply_date apps_prev_180_days
1 01-06-2014 0
1 01-07-2014 1
1 01-04-2018 0
1 01-07-2018 1
2 01-04-2015 0
2 01-05-2015 1
2 01-06-2015 2
2 01-09-2015 3

我尝试在窗口函数中创建滞后变量并计算应用程序,但是这只考虑了以前的应用程序而不是所有应用程序。 任何指针如何做到这一点?

【问题讨论】:

标签: python dataframe apache-spark pyspark


【解决方案1】:

我们可以使用Window 函数和.rangeBetween 方法(以秒为单位)来定义自定义时间间隔

import pyspark.sql.functions as F
from pyspark.sql.window import Window

# convert string type to actual date (if not done yet)
df = df.withColumn('apply_date', F.to_date('apply_date', 'dd-MM-yyyy'))

# number of days and seconds for time interval
days = 180
unix_seconds = days * 86400

# define window
w = Window\
  .partitionBy('cust_id')\
  .orderBy(F.col('apply_date').cast('timestamp').cast('long'))\
  .rangeBetween(-unix_seconds, -1)

df = df.withColumn('apps_prev_180_days', F.count('cust_id').over(w))

df.show()

+-------+----------+------------------+
|cust_id|apply_date|apps_prev_180_days|
+-------+----------+------------------+
|      1|2014-06-01|                 0|
|      1|2014-07-01|                 1|
|      1|2018-04-01|                 0|
|      1|2018-07-01|                 1|
|      2|2015-04-01|                 0|
|      2|2015-05-01|                 1|
|      2|2015-06-01|                 2|
|      2|2015-09-01|                 3|
+-------+----------+------------------+

在这种情况下,.rangeBetween(-unix_seconds, -1) 定义了从 180 天前到上一秒 (-1) 的时间间隔;这允许我们从计数中排除当前应用程序。

【讨论】:

  • 感谢@RicS 的回答。按预期工作。
【解决方案2】:

试试这个:

from pyspark.sql import functions as F, Window as W

df.withColumn(
    "apps_prev_180_days",
    F.count("*").over(
        W.partitionBy("cust_id")
        .orderBy(F.unix_timestamp("apply_date"))  # Date as unix timestamp (seconds)
        .rangeBetween(-(180 * 24 * 3600), -1)  # 180 days in secondes
    ),
).show()

+-------+----------+------------------+
|cust_id|apply_date|apps_prev_180_days|
+-------+----------+------------------+
|      1|2014-06-01|                 0|
|      1|2014-07-01|                 1|
|      1|2018-04-01|                 0|
|      1|2018-07-01|                 1|
|      2|2015-04-01|                 0|
|      2|2015-05-01|                 1|
|      2|2015-06-01|                 2|
|      2|2015-09-01|                 3|
+-------+----------+------------------+

【讨论】:

  • 嗨史蒂文,毫无疑问你是自己做的,但恐怕它看起来与我之前的答案非常相似(如果不是几乎相等)
  • @RicS 对不起......我可能正在输入它,而你也发布了你的答案。尽管如此,使用的功能并不完全相同,您的答案在解释方面更加完整
  • 感谢您抽出宝贵时间回答我的问题。不幸的是,我只能接受一个答案,因此我接受了@RicS 的答案。
  • @akp 没有问题,这很公平:)他的回答更明确;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-04
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多