PySpark UDF无法识别参数数量

时间:2019-10-16 09:43:21

标签: apache-spark pyspark

我定义了一个带有三个参数的Python函数“ DateTimeFormat”

  
      
  1. 具有日期格式(字符串)的Spark Dataframe列
  2.   
  3. 列值的输入格式,例如yyyy-mm-dd(字符串)
  4.   
  5. 输出格式,即必须以yyyymmdd(String)的形式返回输入的格式
  6.   

我现在已在Pyspark中将此功能注册为UDF。 udf_date_time = udf(DateTimeFormat,StringType())

我正在尝试在数据帧选择中调用此UDF,只要输入格式和输出与下面所示不同,它似乎就可以正常工作

df.select(udf_date_time('entry_date',lit('mmddyyyy'),lit('yyyy-mm-dd')))

但是当输入格式和输出格式相同但出现以下错误时,它将失败

df.select('exit_date',udf_date_time('exit_date',lit('yyyy-mm-dd'),lit('yyyy-mm-dd')))

  
    

“ DateTimeFormat”恰好接受3个参数。给出2个

  

但是我显然要向UDF发送三个参数

我已经在Python 2.7和Spark 2.1上尝试了上面的示例

当输入和输出格式相同时,该功能似乎可以在正常的Python中正常工作

>>>DateTimeFormat('10152019','mmddyyyy','mmddyyyy')
'10152019'
>>>

但是在SPARK中运行时,以下代码给出了错误

import datetime
# Standard date,timestamp formatter
# Takes string date, its format and output format as arguments
# Returns string formatted date
def DateTimeFormat(col,in_frmt,out_frmt):   
    date_formatter ={'yyyy':'%Y','mm':'%m','dd':'%d','HH':'%H','MM':'%M','SS':'%S'}
    for key,value in date_formatter.items():
        in_frmt = in_frmt.replace(key,value)
        out_frmt = out_frmt.replace(key,value)
    return datetime.datetime.strptime(col,in_frmt).strftime(out_frmt)

使用下面的代码调用UDF

from pyspark.sql.functions import udf,lit
from pyspark.sql import SparkSession
from pyspark.sql.types import StringType
# Create SPARK session
spark = SparkSession.builder.appName("DateChanger").enableHiveSupport().getOrCreate()

df = spark.read.format("csv").option("header", "true").load(file_path)

# Registering UDF
udf_date_time = udf(DateTimeFormat,StringType())

df.select('exit_date',udf_date_time('exit_date',lit('yyyy-mm-dd'),lit('yyyy-mm-dd'))).show()

CSV文件输入Input file

预期结果是命令

df.select('exit_date',udf_date_time('exit_date',lit('yyyy-mm-dd'),lit('yyyy-mm-dd'))).show()

不应抛出任何错误,例如 DateTimeFormat恰好接受3个参数,但给定2个参数

1 个答案:

答案 0 :(得分:0)

我不确定是否有更好的方法可以这样做,但是您可以尝试以下方法。

在这里,我假设您希望日期设置为特定格式,并在out_frmt='yyyy-mm-dd'函数中为输出格式(DateTimeFormat)设置了默认值

我添加了一个名为udf_score的新函数来帮助进行转换。这可能会让您感兴趣

from pyspark.sql.types import StringType
from pyspark.sql.functions import udf, lit


df = spark.createDataFrame([
    ["10-15-2019"],
    ["10-16-2019"],
    ["10-17-2019"],
], ['exit_date'])

import datetime
def DateTimeFormat(col,in_frmt,out_frmt='yyyy-mm-dd'):
    date_formatter ={'yyyy':'%Y','mm':'%m','dd':'%d','HH':'%H','MM':'%M','SS':'%S'}
    for key,value in date_formatter.items():
        in_frmt = in_frmt.replace(key,value)
        out_frmt = out_frmt.replace(key,value)
    return datetime.datetime.strptime(col,in_frmt).strftime(out_frmt)

def udf_score(in_frmt):
    return udf(lambda l: DateTimeFormat(l, in_frmt))

in_frmt = 'mm-dd-yyyy'
df.select('exit_date',udf_score(in_frmt)('exit_date').alias('new_dates')).show()
+----------+----------+
| exit_date| new_dates|
+----------+----------+
|10-15-2019|2019-10-15|
|10-16-2019|2019-10-16|
|10-17-2019|2019-10-17|
+----------+----------+