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

时间:2018-09-19 19:03:10

标签: apache-spark pyspark apache-spark-sql date-range

我有一些带有"date"列的DataFrame,并且我试图从"date"列中生成一个新的DataFrame,其中包含每月的时间戳,该时间戳都在最小日期和最大日期之间。

解决方案之一如下:

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天。可以通过某种方式使其更加精确吗?

请注意:稍后,我只需要 year month 值,因此我将忽略日期和时间。但是无论如何,因为我正在生成一个很大的日期范围(2001年至2018年)之间的时间戳,所以时间戳发生了变化。

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

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

我检查了一下,从2001年到2018年仅跳过了3个月。

1 个答案:

答案 0 :(得分:3)

假设您具有以下DataFrame:

%timeit df['players_combine'] = df.apply(lambda x: x[x.notnull()].max(), axis=1)

1 loop, best of 3: 4.86 s per loop

您可以按照与my answerthis question相同的方法,在data = [("2000-01-01","2002-12-01")] df = spark.createDataFrame(data, ["minDate", "maxDate"]) df.show() #+----------+----------+ #| minDate| maxDate| #+----------+----------+ #|2000-01-01|2002-12-01| #+----------+----------+ date之间的所有月份中添加列minDate

只需将maxDate替换为pyspark.sql.functions.datediff,然后使用pyspark.sql.functions.months_between而不是add_months

date_add