从同一个源加入两个DataFrame

时间:2015-04-21 15:25:26

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

我使用的是pyspark(Apache Spark)的DataFrame API,遇到了以下问题:

当我加入两个源自相同源DataFrame的DataFrame时,生成的DF将爆炸到大量行。一个简单的例子:

我从磁盘加载了n行的DataFrame:

df = sql_context.parquetFile('data.parquet')

然后我从该源创建两个DataFrame。

df_one = df.select('col1', 'col2')
df_two = df.select('col1', 'col3')

最后,我想(内部)将它们重新组合在一起:

df_joined = df_one.join(df_two, df_one['col1'] == df_two['col1'], 'inner')

col1中的密钥是唯一的。生成的DataFrame应该有n行,但它确实有n*n行。

当我直接从磁盘加载df_onedf_two时,这种情况不会发生。我在Spark 1.3.0上,但这也发生在当前的1.4.0快照上。

有人可以解释为什么会这样吗?

2 个答案:

答案 0 :(得分:4)

如果我正确读取,df_two没有col2

    df_one = df.select('col1', 'col2')
    df_two = df.select('col1', 'col3')

所以当你这样做时:

    df_one.join(df_two, df_one['col1'] == df_two['col2'], 'inner')

那应该失败。如果你想说

    df_one.join(df_two, df_one['col1'] == df_two['col1'], 'inner')

但是,您从同一数据框加载的事实应该没有影响。我建议你这样做:

    df_one.show()
    df_two.show()

确保您选择的数据符合您的预期。

答案 1 :(得分:0)

我在大型数据集中也看到了这个问题,在Spark 1.3上。不幸的是,在小的,人为的例子中,我组成的'join'正常工作。我觉得加入之前的步骤可能存在一些潜在的错误

执行连接(注意:DateTime只是一个字符串):

> join = df1.join(df2, df1.DateTime == df2.DateTime, "inner")
> join.count()

250000L

这显然是返回完整的500 * 500笛卡尔联盟。

对我来说,切换到SQL的作用是什么:

  > sqlc.registerDataFrameAsTable(df1, "df1")
  > sqlc.registerDataFrameAsTable(df2, "df2")
  > join = sqlc.sql("select * from df1, df2 where df1.DateTime = df2.DateTime")
  > join.count()
  471L

该值看起来正确。

看到这个,我个人不会使用pyspark的DataFrame.join(),直到我能更好地理解这种差异。