比较2个pyspark dataframe列,并在此基础上更改另一列的值

比较2个pyspark dataframe列,并在此基础上更改另一列的值,pyspark,Pyspark,我有一个问题,我已经从我写的图形算法生成了一个数据帧。问题是,我希望在每次运行图形代码之后,基本组件的值保持不变 这是生成的示例数据帧: df = spark.createDataFrame( [ (1, 'A1'), (1, 'A2'), (1, 'A3'), (2, 'B1'), (2, 'B2'), (3, 'B3'), (4, 'C1'), (4, '

我有一个问题,我已经从我写的图形算法生成了一个数据帧。问题是,我希望在每次运行图形代码之后,基本组件的值保持不变

这是生成的示例数据帧:

df = spark.createDataFrame(
    [
        (1, 'A1'), 
        (1, 'A2'),
        (1, 'A3'),
        (2, 'B1'),
        (2, 'B2'),
        (3, 'B3'),
        (4, 'C1'),
        (4, 'C2'),
        (4, 'C3'),
        (4, 'C4'),
        (5, 'D1'),
    ],
    ['old_comp_id', 'db_id'] 
)
在另一次运行后,值会完全改变,因此新运行的值如下所示

df2 = spark.createDataFrame(
    [
        (2, 'A1'), 
        (2, 'A2'),
        (2, 'A3'),
        (3, 'B1'),
        (3, 'B2'),
        (3, 'B3'),
        (1, 'C1'),
        (1, 'C2'),
        (1, 'C3'),
        (1, 'C4'),
        (4, 'D1'),
    ],
    ['new_comp_id', 'db_id'] 
)

因此,我需要做的事情是比较上述两个数据帧之间的值,并根据关联的数据库id更改组件id的值

  • 如果数据库id相同,则将组件id更新为来自第一个数据帧
  • 如果它们不同,则分配一个全新的组件id(新组件id=最大值(旧组件id)+1)
  • 这就是我到目前为止的想法:

    old_ids = df.groupBy("old_comp_id").agg(F.collect_set(F.col("db_id")).alias("old_db_id"))
    new_ids = df2.groupBy("new_comp_id").agg(F.collect_set(F.col("db_id")).alias("new_db_id"))
    
    joined = new_ids.join(old_ids,old_ids.old_comp_id == new_ids.new_comp_id,"outer")
    
    joined.withColumn("update_comp", F.when( F.col("new_db_id") == F.col("old_db_id"), F.col('old_comp_id')).otherwise(F.max(F.col("old_comp_id")+1))).show()
    

    为了在非聚合列中使用聚合函数,应该使用窗口函数

    首先,使用db_id连接DFs:

    from pyspark.sql.functions import when, col, max
    joinedDF = df.join(df2, df["db_id"] == df2["new_db_id"], "outer")
    
    然后,开始构建窗口(在其中按db_id分组,并按old_comp_id排序),以便在第一行中具有最高值的old_comp_id

    from pyspark.sql.window import Window
    from pyspark.sql.functions import desc
    windowSpec = Window\
    .partitionBy("db_id")\
    .orderBy(desc("old_comp_id"))\
    .rowsBetween(Window.unboundedPreceding, Window.currentRow)
    
    然后,使用windowSpec构建max列

    from pyspark.sql.functions import max
    maxCompId = max(col("old_comp_id")).over(windowSpec)
    
    然后,将其应用于“选择”

    joinedDF.select(col("db_id"), when(col("new_db_id").isNotNull(), col("old_comp_id")).otherwise(maxCompId+1).alias("updated_comp")).show()
    
    有关更多信息,请参阅文档()

    希望这有帮助