我有一个用户定义的函数,我想用它来导出我的数据框中的新列:
def to_date_formatted(date_str, format):
if date_str == '' or date_str is None:
return None
try:
dt = datetime.datetime.strptime(date_str, format)
except:
return None
return dt.date()
spark.udf.register("to_date_udf", to_date_formatted, DateType())
我可以通过运行像select to_date_udf(my_date, '%d-%b-%y') as date
这样的sql来使用它。注意能够将自定义格式作为参数传递给函数
但是,我很难使用pyspark列表达式语法而不是sql
来使用它我想写一些类似的东西:
df.with_column("date", to_date_udf('my_date', %d-%b-%y')
但这会导致错误。我怎么能这样做?
[编辑:在此特定示例中,在Spark 2.2+中,您可以使用内置的to_date
函数提供可选的格式参数。我现在在Spark 2.0上,所以这对我来说是不可能的。另外值得注意的是我提供了这个例子,但我对提供UDF参数的一般语法感兴趣,而不是日期转换的具体细节]
答案 0 :(得分:5)
我找到了三种方法来实现这一目标:
import pandas as pd
import datetime
from pyspark import SparkContext, SparkConf
from pyspark.sql import SparkSession
from pyspark.sql.types import DateType
from pyspark.sql.functions import expr, lit
sc = SparkContext.getOrCreate()
spark = SparkSession(sc)
def to_date_formatted(date_str, format):
if date_str == '' or date_str is None:
return None
try:
dt = datetime.datetime.strptime(date_str, format)
except:
return None
return dt.date()
data = {}
data["date_str_1"] = ["01-Dec-17", "05-Jan-12", "08-Mar-15"]
data["date_str_2"] = ["01/12/17", "05/01/12", "08/03/15"]
df = pd.DataFrame(data)
df = spark.createDataFrame(df)
df.registerTempTable('df')
from pyspark.sql.functions import udf
to_date_udf = udf(to_date_formatted, DateType())
df = df.withColumn("parsed_date", to_date_udf('date_str_1', lit('%d-%b-%y')))
df.show()
spark.udf.register("to_date_udf", to_date_formatted, DateType())
ex = "to_date_udf(date_str_1, '%d-%b-%y') as d"
df = df.withColumn("parsed_date", expr(ex))
df.show()
选项3只是为了讨论to_date_formatted
函数:
from functools import partial
curried_to_date = partial(to_date_formatted, format="%d-%b-%y")
curried_to_date = udf(curried_to_date, DateType())
df.withColumn("parsed_date", curried_to_date('date_str_1'))
答案 1 :(得分:1)
只需使用to_date
:
from pyspark.sql.functions import to_date
df.withColumn("date_str_1_", to_date("date_str_1", "dd-MMM-yy")).show()
# +----------+----------+-----------+
# |date_str_1|date_str_2|date_str_1_|
# +----------+----------+-----------+
# | 01-Dec-17| 01/12/17| 2017-12-01|
# | 05-Jan-12| 05/01/12| 2012-01-05|
# | 08-Mar-15| 08/03/15| 2015-03-08|
# +----------+----------+-----------+
df.withColumn("date_str_2_", to_date("date_str_2", "dd/MM/yy")).show()
# +----------+----------+-----------+
# |date_str_1|date_str_2|date_str_2_|
# +----------+----------+-----------+
# | 01-Dec-17| 01/12/17| 2017-12-01|
# | 05-Jan-12| 05/01/12| 2012-01-05|
# | 08-Mar-15| 08/03/15| 2015-03-08|
# +----------+----------+-----------+