python - 计算 pyspark 中日期范围的 ID
问题描述
我有一个 pyspark 数据框,其中包含 parsed_date (dtype: date) 和 id (dtype: bigint) 列,如下所示:
+-------+-----------+
| id|parsed_date|
+-------+-----------+
|1471783| 2017-12-18|
|1471885| 2017-12-18|
|1472928| 2017-12-19|
|1476917| 2017-12-19|
|1477469| 2017-12-21|
|1478190| 2017-12-21|
|1478570| 2017-12-19|
|1481415| 2017-12-21|
|1472592| 2017-12-20|
|1474023| 2017-12-22|
|1474029| 2017-12-22|
|1474067| 2017-12-24|
+-------+-----------+
我有一个如下所示的功能。目的是传递日期(天)和 t(天数)。在 df1 中,id 计入范围(day-t,day),而在 df2 中,id 计入范围(day,day+t)。
def hypo_1(df, day, t):
df1 = (df.filter(f"parsed_date between '{day}' - interval {t} days and '{day}' - interval 1 day")
.withColumn('count_before', F.count('id').over(Window.partitionBy('parsed_date')))
.orderBy('parsed_date')
)
df2 = (df.filter(f"parsed_date between '{day}' + interval 1 day and '{day}' + interval {t} days")
.withColumn('count_after', F.count('id').over(Window.partitionBy('parsed_date')))
.orderBy('parsed_date')
)
return [df1, df2]
df1, df2 = hypo_1(df, '2017-12-20', 2)
df1.show()
+-------+-----------+------------+
| id|parsed_date|count_before|
+-------+-----------+------------+
|1471783| 2017-12-18| 2|
|1471885| 2017-12-18| 2|
|1472928| 2017-12-19| 3|
|1476917| 2017-12-19| 3|
|1478570| 2017-12-19| 3|
+-------+-----------+------------+
df2.show()
+-------+-----------+-----------+
| id|parsed_date|count_after|
+-------+-----------+-----------+
|1481415| 2017-12-21| 3|
|1478190| 2017-12-21| 3|
|1477469| 2017-12-21| 3|
|1474023| 2017-12-22| 2|
|1474029| 2017-12-22| 2|
+-------+-----------+-----------+
我想知道如果范围内缺少日期,如何修复此代码?假设没有记录2017-12-22
?是否有可能立即记录在案的日期?我的意思是,如果2017-12-22
不在那里,并且下一个日期2017-12-21
是2017-12-24
,那么有可能以某种方式接受吗?
感谢 mck帮助创建函数hypo_1(df, day, t)
。
解决方案
我删除了2017-12-22
行来说明。这个想法是dense_rank
按日期排序(之前降序,之后升序),并过滤排名 <= 2 的行,即两个最接近的日期。
from pyspark.sql import functions as F, Window
def hypo_1(df, day, t):
df1 = (df.filter(f"parsed_date < '{day}'")
.withColumn('rn', F.dense_rank().over(Window.orderBy(F.desc('parsed_date'))))
.filter('rn <= 2')
.drop('rn')
.withColumn('count_before', F.count('id').over(Window.partitionBy('parsed_date')))
.orderBy('parsed_date')
)
df2 = (df.filter(f"parsed_date > '{day}'")
.withColumn('rn', F.dense_rank().over(Window.orderBy('parsed_date')))
.filter('rn <= 2')
.drop('rn')
.withColumn('count_after', F.count('id').over(Window.partitionBy('parsed_date')))
.orderBy('parsed_date')
)
return [df1, df2]
df1, df2 = hypo_1(df, '2017-12-20', 2)
df1.show()
+-------+-----------+------------+
| id|parsed_date|count_before|
+-------+-----------+------------+
|1471783| 2017-12-18| 2|
|1471885| 2017-12-18| 2|
|1472928| 2017-12-19| 3|
|1476917| 2017-12-19| 3|
|1478570| 2017-12-19| 3|
+-------+-----------+------------+
df2.show()
+-------+-----------+-----------+
| id|parsed_date|count_after|
+-------+-----------+-----------+
|1477469| 2017-12-21| 3|
|1481415| 2017-12-21| 3|
|1478190| 2017-12-21| 3|
|1474067| 2017-12-24| 1|
+-------+-----------+-----------+
推荐阅读
- java - 如何使用意图将变量从 MainActivity 传递到 ListAdapter
- ruby-on-rails - 如何通过 SwiftUI urlSession 中的 REST API 将图像数组上传到 Rails 活动存储后端
- html - 我将如何创建一个具有 1 个输入和 6 个不同输出的价格计算器?
- webpack - Webpack 控制台输出
- css - 在滚动负载上居中元素
- javascript - Vue 在每次小的更改时都会不必要地重新渲染整个所有子组件
- xslt-1.0 - 根据条件应用 XSLT
- php - 多个 And 是否在 mysql 中工作
- python - 如何在行数据框中选择数据 3 次更大的阈值 - 熊猫
- javascript - 如何在 vue.js 中将数据属性添加到 html 标签