PySpark DataFrame列对比:删除城市对往返距离重复行实现咨询
PySpark 实现无序城市对重复数据去重
核心思路是为每一行的两个城市生成与顺序无关的唯一标识,相同两个城市无论顺序如何标识完全一致,再基于标识去重即可。
方法1:使用least/greatest + dropDuplicates(最简单高效)
适用于不需要指定保留哪一行,只要去重即可的场景:
from pyspark.sql import functions as F # 核心处理逻辑 df2 = df1 \ # 生成与顺序无关的两个分组键:取两个城市字典序更小/更大的值 .withColumn("city_min", F.least(F.col("city1"), F.col("city2"))) \ .withColumn("city_max", F.greatest(F.col("city1"), F.col("city2"))) \ # 按分组键+距离去重,相同分组只保留任意一行 .dropDuplicates(["city_min", "city_max", "dist"]) \ # 删除辅助列得到最终结果 .drop("city_min", "city_max")
如果你的业务逻辑已经保证相同两个城市的距离完全一致,也可以去掉dist字段,只按city_min和city_max两个字段去重。
方法2:使用窗口函数(支持自定义保留规则)
如果需要固定保留符合某规则的行,比如固定保留city1字典序更小的行,可使用窗口函数实现:
from pyspark.sql import functions as F from pyspark.sql import Window # 定义窗口分区规则,与顺序无关的城市对+距离作为分区键 window_spec = Window.partitionBy( F.least(F.col("city1"), F.col("city2")), F.greatest(F.col("city1"), F.col("city2")), F.col("dist") # 排序规则可自定义,比如写orderBy(F.col("city1"))就是固定保留city1更小的行 ).orderBy(F.lit(1)) df2 = df1 \ .withColumn("row_num", F.row_number().over(window_spec)) \ # 只保留每个分组的第一行 .filter(F.col("row_num") == 1) \ .drop("row_num")
两种方法都可以对示例输入完成去重,得到你给出的预期输出结果。
内容的提问来源于stack exchange,提问作者user3495160
相关产品推荐
相关产品推荐

