PySpark DataFrame过滤两列相等行失效问题排查
问题分析与解决方案
你的代码核心问题出在Null值的比较逻辑上,Spark遵循SQL的三值逻辑(True/False/Null):
- 当
previous_plan是Null时,Null != '1mo'这类比较的结果是Null,而filter只保留条件结果为True的行,Null会被当作False处理。 - 你说实际返回全部7行,大概率是没把过滤后的结果赋值给新变量,直接打印了原始的
df;如果严格执行你的代码,正确结果应该只保留event_id6,而非全部行。
要实现「过滤掉previous_plan等于new_plan的行,保留Null行」的需求,需要用Spark的NULL-safe比较运算符来处理,有两种可行方案:
修正后的代码
方案1:使用NULL-safe不等于判断(推荐)
from pyspark.sql import functions as F filtered_df = df.selectExpr("event_id", "previous_plan", "new_plan") \ .filter(F.not(F.col("previous_plan") <=> F.col("new_plan")))
方案2:显式处理Null情况
from pyspark.sql import functions as F filtered_df = df.selectExpr("event_id", "previous_plan", "new_plan") \ .filter((F.col("previous_plan") != F.col("new_plan")) | F.isnull(F.col("previous_plan")))
逻辑说明
<=>是Spark的NULL-safe相等运算符:两个值完全相等(包括都是Null)时返回True,否则返回False。用F.not()取反后,就能精准匹配「值不相等,或其中一个为Null」的场景,正好符合你的需求。- 方案2通过逻辑或显式包含
previous_plan为Null的情况,逻辑更直观,但代码稍繁琐。
执行修正后的代码后,就能得到你预期的结果:过滤掉event_id3、4、7,保留1、2、5、6的行。
内容的提问来源于stack exchange,提问作者DSolei
相关产品推荐
相关产品推荐

