在pyspark数据框中的两个日期之间生成每月时间戳

Posted

技术标签:

【中文标题】在pyspark数据框中的两个日期之间生成每月时间戳【英文标题】:Generating monthly timestamps between two dates in pyspark dataframe 【发布时间】:2018-09-19 19:03:10 【问题描述】:

我有一些带有"date" 列的DataFrame,我正在尝试生成一个新的DataFrame,其中包含"date" 列的最小和最大日期之间的所有月度时间戳

其中一个解决方案如下:

month_step = 31*60*60*24

min_date, max_date = df.select(min_("date").cast("long"), max_("date").cast("long")).first()

df_ts = spark.range(
    (min_date / month_step) * month_step, 
    ((max_date / month_step) + 1) * month_step,
    month_step
).select(col("id").cast("timestamp").alias("yearmonth"))

df_formatted_ts = df_ts.withColumn(
    "yearmonth",
    f.concat(f.year("yearmonth"), f.lit('-'), format_string("%02d", f.month("yearmonth")))
).select('yearmonth')

df_formatted_ts.orderBy(asc('yearmonth')).show(150, False)

问题是我将month_step 视为 31 天,它并不真正正确,因为有些月份有 30 天甚至 28 天。有可能以某种方式使其更精确吗?

仅作说明:稍后我只需要 yearmonth 值,因此我将忽略日期和时间。但无论如何,因为我在相当大的日期范围(2001 年到 2018 年之间)之间生成时间戳,所以时间戳会发生变化。

这就是为什么有时会跳过几个月。例如,此快照缺少 2010-02:

|2010-01  |
|2010-03  |
|2010-04  |
|2010-05  |
|2010-06  |
|2010-07  |

我查了一下,从 2001 年到 2018 年只有 3 个月。

【问题讨论】:

真的吗?你能看两行以上的帖子吗 看看this post- 每天都会这样做,但改成每月应该不会太难 【参考方案1】:

假设您有以下 DataFrame:

data = [("2000-01-01","2002-12-01")]
df = spark.createDataFrame(data, ["minDate", "maxDate"])
df.show()
#+----------+----------+
#|   minDate|   maxDate|
#+----------+----------+
#|2000-01-01|2002-12-01|
#+----------+----------+

您可以按照与my answer 到this question 相同的方法添加一个列date,其中包含minDatemaxDate 之间的所有月份。

只需将pyspark.sql.functions.datediff 替换为pyspark.sql.functions.months_between,并使用add_months 代替date_add

import pyspark.sql.functions as f

df.withColumn("monthsDiff", f.months_between("maxDate", "minDate"))\
    .withColumn("repeat", f.expr("split(repeat(',', monthsDiff), ',')"))\
    .select("*", f.posexplode("repeat").alias("date", "val"))\
    .withColumn("date", f.expr("add_months(minDate, date)"))\
    .select('date')\
    .show(n=50)
#+----------+
#|      date|
#+----------+
#|2000-01-01|
#|2000-02-01|
#|2000-03-01|
#|2000-04-01|
# ...skipping some rows...
#|2002-10-01|
#|2002-11-01|
#|2002-12-01|
#+----------+

【讨论】:

以上是关于在pyspark数据框中的两个日期之间生成每月时间戳的主要内容,如果未能解决你的问题,请参考以下文章

新创建的列在 pyspark 数据框中显示空值

pyspark 中的每月聚合

过滤pySpark数据框中的日期列记录

在 PySpark 中查找两个数据帧之间的变化

检查日期是不是在另一个数据框中的两个日期之间,如果是则操作日期

在pyspark中的两个时间戳之间创建一个时间戳数组