如何在 PySpark 中根据年、月和日创建日期?

How to create date from year, month and day in PySpark?

我有关于年、月和日的三列。我如何使用这些在 PySpark 中创建日期?

您可以使用 concat_ws() 将列与 - 连接起来并转换为日期。

#sampledata
df.show()

#+----+-----+---+
#|year|month|day|
#+----+-----+---+
#|2020|   12| 12|
#+----+-----+---+
from pyspark.sql.functions import *

df.withColumn("date",concat_ws("-",col("year"),col("month"),col("day")).cast("date")).show()
+----+-----+---+----------+
|year|month|day|      date|
+----+-----+---+----------+
|2020|   12| 12|2020-12-12|
+----+-----+---+----------+

#dynamic way
cols=["year","month","day"]
df.withColumn("date",concat_ws("-",*cols).cast("date")).show()
#+----+-----+---+----------+
#|year|month|day|      date|
#+----+-----+---+----------+
#|2020|   12| 12|2020-12-12|
#+----+-----+---+----------+

#using date_format,to_timestamp,from_unixtime(unix_timestamp) functions

df.withColumn("date",date_format(concat_ws("-",*cols),"yyyy-MM-dd").cast("date")).show()
df.withColumn("date",to_timestamp(concat_ws("-",*cols),"yyyy-MM-dd").cast("date")).show()
df.withColumn("date",to_date(concat_ws("-",*cols),"yyyy-MM-dd")).show()
df.withColumn("date",from_unixtime(unix_timestamp(concat_ws("-",*cols),"yyyy-MM-dd"),"yyyy-MM-dd").cast("date")).show()
#+----+-----+---+----------+
#|year|month|day|      date|
#+----+-----+---+----------+
#|2020|   12| 12|2020-12-12|
#+----+-----+---+----------+

对于 Spark 3+,您可以使用 make_date 函数:

df = df.withColumn("date", expr("make_date(year, month, day)"))

在 DataBrick 上使用 pyspark,这是一个纯字符串时的解决方案;不幸的是,unix_timestamp 可能无法正常工作并产生错误的结果。在 pyspark 中使用 unix_timestamp 或 to_date 命令时要非常谨慎。 例如,如果您的字符串有一个类似“20140625”的 fromat,它们只会生成完全错误的输入日期版本。在我的例子中,除了再次构建字符串的连接并将其转换为日期之外,没有其他方法有效。

from pyspark.sql.functions import col, lit, substring, concat

# string format to deal with: "20050627","19900401",...

#Create a new column with a shorter name to keep the originalcolumns as well
df.withColumn("dod",col("date_of_death"))

#create date upon string components
df.withColumn("dod", concat(substring(df.dod,1,4),lit("-"),substring(df.dod,5,2),lit("-"),substring(df.dod,7,2)).cast("date")))

结果如下所示:

请注意使用以下格式。它最有可能和奇怪地产生错误的结果,而不会引发并向您显示任何错误。就我而言,它破坏了我的大部分分析:

### wrong use! use only on strings with delimeters ("yyyy-mm-dd) and be highly causious!
f.to_date(f.unix_timestamp(df.dod,"yyyymmdd").cast("timestamp"))