为什么left_anti join在pyspark中没有按预期工作?

时间:2017-11-13 13:33:32

标签: pyspark-sql anti-join

在数据框中,我试图识别那些在C2列中具有值的行,这些行在任何其他行的C1列中都不存在。我尝试了以下代码:

pscp source user@ip:dest 

现在应用left_anti连接只会返回第4行,但我也会得到第2行:

in_df = sqlContext.createDataFrame([[1,None,'A'],[2,1,'B'],[3,None,'C'],[4,11,'D']],['C1','C2','C3'])
in_df.show()
    +---+----+---+
    | C1|  C2| C3|
    +---+----+---+
    |  1|null|  A|
    |  2|   1|  B|
    |  3|null|  C|
    |  4|  11|  D|
    +---+----+---+
filtered = in_df.filter(in_df.C2.isNotNull())
filtered.show()
    +---+---+---+
    | C1| C2| C3|
    +---+---+---+
    |  2|  1|  B|
    |  4| 11|  D|
    +---+---+---+

如果我'实现'过滤后的DF,结果就像预期的那样:

filtered.join(in_df,(in_df.C1 == filtered.C2), 'left_anti').show()
    +---+---+---+
    | C1| C2| C3|
    +---+---+---+
    |  2|  1|  B|
    |  4| 11|  D|
    +---+---+---+

为什么需要这个.toDF?

1 个答案:

答案 0 :(得分:2)

in_df.C1实际上是引用filtered列,显示以下代码:

in_df = sqlContext.createDataFrame([[1,None,'A'],[2,1,'B'],[3,None,'C'],[4,11,'D']],['C1','C2','C3'])
filtered = in_df.filter(in_df.C2.isNotNull()).select("C2")
filtered.join(in_df,(in_df.C1 == filtered.C2), 'left_anti').show()
  

Py4JJavaError:调用o699.join时发生错误。   :org.apache.spark.sql.AnalysisException:无法解析给定输入列的“in_df.C1”:[C2,C1,C2,C3] ;;   '加入LeftAnti,('in_df.C1 ='filtered.C2)   : - 项目[C2#891L]   :+ - 过滤器isnotnull(C2#891L)   :+ - LogicalRDD [C1#890L,C2#891L,C3#892]   + - LogicalRDD [C1#900L,C2#901L,C3#902]

所以基本上在加入2个数据帧时,实际上使用条件filtered.C1 == filtered.C2

filtered = in_df.filter(in_df.C2.isNotNull())
filtered.join(in_df,(filtered.C1 == filtered.C2), 'left_anti').show()

    +---+---+---+
    | C1| C2| C3|
    +---+---+---+
    |  2|  1|  B|
    |  4| 11|  D|
    +---+---+---+

您可能更改了数据框的名称,但其中的列仍可以调用in_df.Ci。为了确保您引用正确的数据帧,您可以使用别名:

import pyspark.sql.functions as psf
filtered.alias("filtered").join(in_df.alias("in_df"),(psf.col("in_df.C1") == psf.col("filtered.C2")), 'left_anti').show()

    +---+---+---+
    | C1| C2| C3|
    +---+---+---+
    |  4| 11|  D|
    +---+---+---+

处理列名模糊的最佳方法是从一开始就避免使用它们(重命名列或使用数据框的别名)。