Pyspark 获取Spark数据框中两个日期之间的所有日期
我有一个DF,其中有Pyspark 获取Spark数据框中两个日期之间的所有日期,pyspark,apache-spark-sql,Pyspark,Apache Spark Sql,我有一个DF,其中有bookingDt和arrivalDt列。我需要找出这两个日期之间的所有日期 示例代码: df=spark.sparkContext.parallelize( [Row(vyge_id=1000,bookingDt='2018-01-01',arrivalDt='2018-01-05'))。toDF() diffDaysDF=df.withColumn(“diffDays”,datediff('arrivalDt','bookingDt')) diffDaysDF.show(
bookingDt
和arrivalDt
列。我需要找出这两个日期之间的所有日期
示例代码:
df=spark.sparkContext.parallelize(
[Row(vyge_id=1000,bookingDt='2018-01-01',arrivalDt='2018-01-05'))。toDF()
diffDaysDF=df.withColumn(“diffDays”,datediff('arrivalDt','bookingDt'))
diffDaysDF.show()
代码输出:
+----------+----------+-------+--------+
|抵达时间|预订时间|维吉id |天数|
+----------+----------+-------+--------+
|2018-01-05|2018-01-01| 1000| 4|
+----------+----------+-------+--------+
我尝试的是找到两个日期之间的天数,并使用timedelta
函数和explode
函数计算所有日期
dateList=[str(bookingDt+timedelta(i))表示范围内的i(diffDays)]
预期输出:
基本上,我需要为bookingDt
和arrivalDt
之间的每个日期创建一个DF,包括这两个日期
+----------+----------+-------+----------+
|arrivalDt | bookingDt | vyge | id | txnDt|
+----------+----------+-------+----------+
|2018-01-05|2018-01-01| 1000|2018-01-01|
+----------+----------+-------+----------+
|2018-01-05|2018-01-01| 1000|2018-01-02|
+----------+----------+-------+----------+
|2018-01-05|2018-01-01| 1000|2018-01-03|
+----------+----------+-------+----------+
|2018-01-05|2018-01-01| 1000|2018-01-04|
+----------+----------+-------+----------+
|2018-01-05|2018-01-01| 1000|2018-01-05|
+----------+----------+-------+----------+
好吧,你可以做以下事情
创建仅包含日期的数据框:
日期_df
#第一次预订日期
和最后一次到达日期
然后将这些df连接到中间条件:
df.join(dates_df,
on=col('dates_df.dates').between(col('df.bookindDt'), col('dt.arrivalDt'))
.select('df.*', 'dates_df.dates')
它可能比使用explode
的解决方案工作得更快,但是您需要确定此df的开始和结束日期。
10年df将只有3650条记录,不需要太多担心。只要您使用Spark 2.1版或更高版本,您就可以利用我们在使用时可以使用的事实:
- 创建长度等于
diffDays
- 在“
上拆分此字符串,将其转换为大小为”和“
diffDays
- 用于分解此数组及其索引
- 最后使用将索引值天数添加到
bookingDt
导入pyspark.sql.f函数
diffDaysDF.withColumn(“repeat”,f.expr(“split(repeat(',',',,diffDays),,,'))”)\
.选择(“*”,f.posexplode(“重复”)。别名(“txnDt”,“val”))\
.drop(“重复”、“val”、“diffDays”)\
.带列(“txnDt”,f.expr(“日期添加(预订日期,txnDt)”)\
.show()
#+----------+----------+-------+----------+
#|arrivalDt | bookingDt | vyge | id | txnDt|
#+----------+----------+-------+----------+
#|2018-01-05|2018-01-01| 1000|2018-01-01|
#|2018-01-05|2018-01-01| 1000|2018-01-02|
#|2018-01-05|2018-01-01| 1000|2018-01-03|
#|2018-01-05|2018-01-01| 1000|2018-01-04|
#|2018-01-05|2018-01-01| 1000|2018-01-05|
#+----------+----------+-------+----------+
正如@vvg建议的那样:
#我想Bookindt的日期范围包括arrivalDt,
#否则,您必须找到Bookindt和arrivalDt的唯一日期的交叉点
日期_df=df.select('bookindDt').distinct()
dates_df=dates_df.with ColumnRename('Bookindt','day_of_listing')
listing_days_df=df.join(dates_df,on=dates_df.day_of_listing.between(df.bookindDt,df.arrivalDt))
输出:
+----------+----------+-------+-------------------+
|arrivalDt | bookingDt | vyge | id |上市日||
+----------+----------+-------+-------------------+
|2018-01-05|2018-01-01| 1000|2018-01-01 |
+----------+----------+-------+-------------------+
|2018-01-05|2018-01-01| 1000|2018-01-02 |
+----------+----------+-------+-------------------+
|2018-01-05|2018-01-01| 1000|2018-01-03 |
+----------+----------+-------+-------------------+
|2018-01-05|2018-01-01| 1000|2018-01-04 |
+----------+----------+-------+-------------------+
|2018-01-05|2018-01-01| 1000|2018-01-05 |
+----------+----------+-------+-------------------+
ForSpark 2.4+可用于创建一个数组,其中包含bookingDt
和arrivalDt
之间的所有日期。然后可以分解此阵列
从pyspark.sql导入函数为F
df=df\
.withColumn('bookingDt',F.col('bookingDt')。cast('date'))\
.withColumn('arrivalDt',F.col('arrivalDt')。cast('date'))
df.带列('txnDt',F.爆炸(F.expr('sequence(预订、到达、间隔1天)))\
.show()
输出:
+-------+----------+----------+----------+
|vyge|u id | bookingDt | arrivalDt | txnDt|
+-------+----------+----------+----------+
| 1000|2018-01-01|2018-01-05|2018-01-01|
| 1000|2018-01-01|2018-01-05|2018-01-02|
| 1000|2018-01-01|2018-01-05|2018-01-03|
| 1000|2018-01-01|2018-01-05|2018-01-04|
| 1000|2018-01-01|2018-01-05|2018-01-05|
+-------+----------+----------+----------+
这正是我想要的。。但是否有可能改善这一点。似乎相当复杂。一种方法可能是创建一个日期数据框,与使用此方法建议的@Volodymyr连接。基本上选择最小预订日期和最大到达日期,计算以天为单位的差异,并创建一个数据帧,其中所有日期都在这两个日期之间。