Pyspark逐行遍历df1并在df2中匹配对应注册周期的实现问题咨询
PySpark 实现学生注册日期匹配注册周期方案
该需求不需要逐行遍历DataFrame,直接使用PySpark原生的范围关联即可实现,性能远高于自定义遍历或UDF方案,具体实现步骤如下:
前置准备:统一日期字段类型
两个DataFrame中的日期字段默认是字符串格式,直接进行大小比较会出现逻辑错误,首先需要转换为Date类型:
from pyspark.sql import functions as F # 转换学生表日期字段,输入格式为dd-MM-yyyy df1 = df1.withColumn("registration_date", F.to_date(F.trim(F.col("registration_date")), "dd-MM-yyyy")) # 转换周期表的起止日期字段 df2 = df2.withColumn("start_date", F.to_date(F.trim(F.col("start_date")), "dd-MM-yyyy")) \ .withColumn("end_date", F.to_date(F.trim(F.col("end_date")), "dd-MM-yyyy"))
这里加
trim是为了避免字段值前后有多余空格导致日期转换失败
执行范围关联获取结果
直接使用带条件的join即可匹配对应周期,由于你提供的周期是连续不重叠的,不会出现一对多匹配的情况:
result_df = df1.join( df2, # 关联条件:注册日期落在周期的起止日期范围内 (F.col("registration_date") >= F.col("start_date")) & (F.col("registration_date") <= F.col("end_date")), how="left" # 用left join保留未匹配到周期的学生数据,不需要可改为inner )
可选:转回字符串格式输出
如果需要和示例一样输出原格式的字符串日期,可以再加一步格式转换:
result_df = result_df.withColumn("registration_date", F.date_format(F.col("registration_date"), "dd-MM-yyyy")) \ .withColumn("start_date", F.date_format(F.col("start_date"), "dd-MM-yyyy")) \ .withColumn("end_date", F.date_format(F.col("end_date"), "dd-MM-yyyy"))
注意事项
不要使用foreach/map等逐行遍历的方式操作分布式DataFrame,这类算子需要将数据拉取到单节点或者频繁序列化,大数据量下性能极差,优先使用Spark原生的SQL算子实现逻辑。
内容的提问来源于stack exchange,提问作者vll1990
相关产品推荐
相关产品推荐

