PySpark.sql.filter没有按预期执行

时间:2018-04-24 07:16:09

标签: python-2.7 apache-spark pyspark apache-spark-sql spark-dataframe

我在执行以下代码时遇到了问题:

from pyspark.sql import functions as F
from pyspark.sql import Row, HiveContext

hc = HiveContext()
rows1 = [Row(id1 = '2', id2 = '1', id3 = 'a'),
         Row(id1 = '3', id2 = '2', id3 = 'a'),
         Row(id1 = '4', id2 = '3', id3 = 'b')]
df1 = hc.createDataFrame(rows1)
df2 = df1.filter(F.col("id3")=="a")
df3 = df1.join(df2, df1.id2 == df2.id1, "inner")

当我运行上面的代码时,df3是一个空的DataFrame。然而: 如果我将代码更改为下面,它将给出正确的结果(2行的DataFrame):

from pyspark.sql import functions as F
from pyspark.sql import Row, HiveContext

hc = HiveContext()
rows1 = [Row(id1 = '2', id2 = '1', id3 = 'a'),
         Row(id1 = '3', id2 = '2', id3 = 'a'),
         Row(id1 = '4', id2 = '3', id3 = 'b')]
df1 = hc.createDataFrame(rows1)
rows2 = [Row(id1 = '2', id2 = '1', id3 = 'a'),
         Row(id1 = '3', id2 = '2', id3 = 'a'),
         Row(id1 = '4', id2 = '3', id3 = 'b')]
df1_temp = hc.createDataFrame(rows2)
df2 = df1_temp.filter(F.col("id3")=="a")
df3 = df1.join(df2, df1.id2 == df2.id1, "inner")

所以我的问题是:为什么我必须在这里创建一个临时数据帧? 另外,如果我无法在项目中获得HiveContext,如何在现有数据框之上创建重复的数据框?

2 个答案:

答案 0 :(得分:5)

我相信你在这里遇到的问题是一个更普遍的问题的实例,其中某些类型的DataFrame自连接(包括DataFrame与其自身的过滤副本的连接)可能导致产生模糊或不正确查询计划。

有几个Spark JIRA与此相关;这里有一些值得注意的:

还有其他JIRA门票处理这些问题的不同表现/方面。这些门票可以通过从上面列出的门票开始的JIRA“涉及”链接链接发现。

这种歧义只会在通过DataFrame实例引用列时产生(通过下标,如df["mycol"],或通过字段访问,如df.mycol)。通过别名DataFrame并通过别名引用列可以避免这种不明确性。例如,以下工作正常:

>>> from pyspark.sql import functions as F
>>> df1 = hc.createDataFrame(rows1).alias("df1")
>>> df2 = df1.filter(F.col("id3")=="a").alias("df2")
>>> df3 = df1.join(df2, F.col("df1.id2") == F.col("df2.id1"), "inner")
>>> df3.show()
+---+---+---+---+---+---+
|id1|id2|id3|id1|id2|id3|
+---+---+---+---+---+---+
|  4|  3|  b|  3|  2|  a|
|  3|  2|  a|  2|  1|  a|
+---+---+---+---+---+---+

答案 1 :(得分:1)

我在Spark 2.0中看到与此数据集相同的行为,但并不总是针对相同的操作。稍微不同的数据框架工作正常。

df1 = spark.createDataFrame(
    [(1, 2, 'a'), (2, 2, 'a'), (3, 4, 'b')], ['id1', 'id2', 'id3']
    )
df1.show()

+---+---+---+
|id1|id2|id3|
+---+---+---+
|  1|  2|  a|
|  2|  2|  a|
|  3|  4|  b|
+---+---+---+

df2 = df1.filter(df1.id3 == 'a')
df2.show()

+---+---+---+
|id1|id2|id3|
+---+---+---+
|  1|  2|  a|
|  2|  2|  a|
+---+---+---+


df3 = df1.join(df2, df1.id2 == df2.id1, 'inner')
df3.show()

+---+---+---+---+---+---+
|id1|id2|id3|id1|id2|id3|
+---+---+---+---+---+---+
|  2|  2|  a|  1|  2|  a|
|  2|  2|  a|  2|  2|  a|
+---+---+---+---+---+---+

一定有错误吗?我没有尝试过后期版本的火花。您可能希望将此报告为错误。