PySpark:如何为每个员工ID生成对应所有月份的多行数据
解决PySpark中员工ID与年月表的全匹配问题
你需要实现的是员工ID表与年月表的笛卡尔积(即每个员工ID对应所有年月记录),之前的错误在于使用了完全不匹配的关联条件(df.GFCID == df2.Yearmonth),导致没有有效匹配结果,出现大量null值。以下是两种可行的解决方案:
方法1:使用crossJoin直接生成笛卡尔积
这是最简洁直接的方式,PySpark的crossJoin方法可以直接生成两个DataFrame的笛卡尔积。
from pyspark.sql import functions as F # 初始化员工ID表 data = [["1"], ["2"], ["3"]] df = spark.createDataFrame(data, ["GFCID"]) # 初始化年月表 data2 = [["202101"], ["202102"], ["202203"], ["202204"], ["202205"]] df2 = spark.createDataFrame(data2, ["Yearmonth"]) # 生成员工与年月的全组合 df_cross = df.crossJoin(df2) # 将数字年月转换为月份名称(如202101转为Jan) df_result = df_cross.withColumn( "Month", F.date_format(F.to_date(F.col("Yearmonth"), "yyyyMM"), "MMM") ).select(F.col("GFCID").alias("ID"), "Month") # 查看结果 df_result.show()
方法2:添加常量列后做全连接
若因环境限制无法使用crossJoin,可以给两个DataFrame添加相同的常量列,再基于该列做连接,同样能实现笛卡尔积效果:
from pyspark.sql import functions as F # 给两个表添加相同的常量连接键 df_with_key = df.withColumn("join_key", F.lit(1)) df2_with_key = df2.withColumn("join_key", F.lit(1)) # 基于常量键做内连接 df_joined = df_with_key.join(df2_with_key, on="join_key", how="inner").drop("join_key") # 转换年月为月份名称并整理列 df_result = df_joined.withColumn( "Month", F.date_format(F.to_date(F.col("Yearmonth"), "yyyyMM"), "MMM") ).select(F.col("GFCID").alias("ID"), "Month") # 查看结果 df_result.show()
两种方法的输出结果一致,示例如下:
+---+-----+ | ID|Month| +---+-----+ | 1| Jan| | 1| Feb| | 1| Mar| | 1| Apr| | 1| May| | 2| Jan| | 2| Feb| | 2| Mar| | 2| Apr| | 2| May| | 3| Jan| | 3| Feb| | 3| Mar| | 3| Apr| | 3| May| +---+-----+
内容的提问来源于stack exchange,提问作者Bigboss9749
相关产品推荐
相关产品推荐

