在数据框中,我试图识别那些在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?
答案 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|
+---+---+---+
处理列名模糊的最佳方法是从一开始就避免使用它们(重命名列或使用数据框的别名)。