Spark中使用UDF计算时间差遇TypeError错误,求解决方案
问题原因
错误出在UDF定义环节:f1 = udf(lambda f_dt, to_dt: (unix_timestamp(to_dt)- unix_timestamp(f_dt)), FloatType() )
- 调用
to_timestamp将字符串转为时间戳类型后,传入UDF的是Python原生datetime对象,但unix_timestamp是Spark SQL函数,仅支持字符串或Column对象作为输入,无法直接处理Python datetime实例,因此触发TypeError。
解决方案
推荐优先使用Spark内置函数(性能远优于Python UDF),以下是两种可行方案:
方案1:直接用Spark内置函数计算时间差
无需UDF,直接通过unix_timestamp作用于Timestamp列计算差值:
from pyspark.sql.types import StringType, FloatType from pyspark.sql.functions import col, to_timestamp, unix_timestamp date_time_d = [("2024-03-15 00:00:00.000", "2024-03-16 12:34:56.789"), ("2024-03-01 00:00:00.000", "2024-03-18 01:23:45.678")] df1 = spark.createDataFrame(date_time_d, ["date_f", "dt_to"]) df1.show() df2 = (df1.withColumn("from_date", to_timestamp(col("date_f"), "yyyy-MM-dd HH:mm:ss.SSS")) .withColumn("to_date", to_timestamp(col("dt_to"), "yyyy-MM-dd HH:mm:ss.SSS")) ) # 直接计算时间差并转为FloatType df4 = df2.withColumn("diff", (unix_timestamp(col("to_date")) - unix_timestamp(col("from_date"))).cast(FloatType())) df4.printSchema() df4.show()
方案2:修改UDF,用Python原生datetime处理
若必须使用UDF,需在UDF内部通过Python原生方法转换时间戳:
from pyspark.sql.types import StringType, FloatType from pyspark.sql.functions import col, to_timestamp, udf import time date_time_d = [("2024-03-15 00:00:00.000", "2024-03-16 12:34:56.789"), ("2024-03-01 00:00:00.000", "2024-03-18 01:23:45.678")] df1 = spark.createDataFrame(date_time_d, ["date_f", "dt_to"]) df1.show() df2 = (df1.withColumn("from_date", to_timestamp(col("date_f"), "yyyy-MM-dd HH:mm:ss.SSS")) .withColumn("to_date", to_timestamp(col("dt_to"), "yyyy-MM-dd HH:mm:ss.SSS")) ) # UDF接收Python datetime对象,用time.mktime转换为时间戳计算差值 f1 = udf(lambda f_dt, to_dt: (time.mktime(to_dt.timetuple()) - time.mktime(f_dt.timetuple())), FloatType() ) df4 = df2.withColumn("diff", f1(col("from_date"),col("to_date"))) df4.printSchema() df4.show()
关键提示
- 优先选用Spark内置函数:内置函数经过分布式优化,性能远超Python UDF,且无需处理类型适配问题。
- UDF内部仅支持Python原生数据类型:不能直接调用Spark SQL函数(此类函数需作用于Column对象)。
内容的提问来源于stack exchange,提问作者Arockia Antony
相关产品推荐
相关产品推荐

