【问题标题】:Pyspark Join and then column select is showing unexpected outputPyspark Join 然后列选择显示意外输出
【发布时间】:2018-06-06 22:43:56
【问题描述】:

我不确定长期工作是否对我这样做,但我在 spark 2.2.0 中看到了一些意想不到的行为

我创建了一个玩具示例,如下所示

toy_df = spark.createDataFrame([
['p1','a'],
['p1','b'],
['p1','c'],
['p2','a'],
['p2','b'],
['p2','d']],schema=['patient','drug']) 

我创建另一个数据框

mdf = toy_df.filter(toy_df.drug == 'c')

如你所知,mdf 是

 mdf.show()
+-------+----+
|patient|drug|
+-------+----+
|     p1|   c|
+-------+----+ 

现在如果我这样做

toy_df.join(mdf,["patient"],"left").select(toy_df.patient.alias("P1"),toy_df.drug.alias('D1'),mdf.patient,mdf.drug).show()

没想到

+---+---+-------+----+
| P1| D1|patient|drug|
+---+---+-------+----+
| p2|  a|     p2|   a|
| p2|  b|     p2|   b|
| p2|  d|     p2|   d|
| p1|  a|     p1|   a|
| p1|  b|     p1|   b|
| p1|  c|     p1|   c|
+---+---+-------+----+

但是如果我使用

toy_df.join(mdf,["patient"],"left").show()

我确实看到了预期的行为

 patient|drug|drug|
+-------+----+----+
|     p2|   a|null|
|     p2|   b|null|
|     p2|   d|null|
|     p1|   a|   c|
|     p1|   b|   c|
|     p1|   c|   c|
+-------+----+----+

如果我在其中一个数据帧上使用别名表达式,我会得到预期的行为

toy_df.join(mdf.alias('D'),on=["patient"],how="left").select(toy_df.patient.alias("P1"),toy_df.drug.alias("D1"),'D.drug').show()

| P1| D1|drug|
+---+---+----+
| p2|  a|null|
| p2|  b|null|
| p2|  d|null|
| p1|  a|   c|
| p1|  b|   c|
| p1|  c|   c|
+---+---+----+

所以我的问题是在加入后选择列的最佳方法是什么,这种行为是否正常

编辑:根据 user8371915,这与标记为
Spark SQL performing carthesian join instead of inner join

的问题相同

但我的问题适用于两个具有相同血统并在调用 show 方法时执行连接但连接后的选择列表现不同的数据框。

【问题讨论】:

  • 由于df.col 或df['col'] 的结果是未绑定到数据帧的Column 类型,我相信结果是预期的。我想知道为什么您在选择错误的情况下没有收到ambiguous column name 错误。
  • 一般来说,DataFrames 之间的连接共享相同的血统会导致微不足道的真/假谓词。这种情况应该是自动处理的,但看起来事情在这里漏掉了。诚实的建议 - 始终使用别名。
  • @user8371915 看起来不像是同一个问题。

标签: apache-spark pyspark


【解决方案1】:

最好的办法是使用别名:

toy_df.alias("toy_df") \
    .join(mdf.alias("mdf"), ["patient"], "left") \
    .select(
        col("patient").alias("P1"),
        col("toy_df.drug").alias("D1"),
        col("patient").alias("patient"),
        col("mdf.drug").alias("drug")
    ) \
    .show()

问题是mdf 是从toy_df 派生的,所以toy_df.drug 和mdf.drug 指的是同一列。因此,当您将这些值传递给 select 时,Spark 也会从同一列返回值。

【讨论】:

    【解决方案2】:

    我能够复制您的发现,我希望我能回答为什么会发生这种情况。但是,我只需更改第二个(右)数据集的别名即可获得您想要的结果。我将 mdf.drug 更改为 mdf.drugs

    mdf = toy_df.filter(toy_df.drug == 'c').select(toy_df.patient,toy_df.drug.alias("drugs"))
    

    所以加入之后..

    toy_df.join(mdf,["patient"],"left").select(toy_df.patient.alias("P1"),toy_df.drug.alias('D1'),mdf.patient,mdf.drugs).show()
    

    我得到了预期的行为

    | P1| D1|patient|drugs|
    +---+---+-------+-----+
    | p2|  a|     p2| null|
    | p2|  b|     p2| null|
    | p2|  d|     p2| null|
    | p1|  a|     p1|    c|
    | p1|  b|     p1|    c|
    | p1|  c|     p1|    c|
    +---+---+-------+-----+
    

    我会做更多的研究,看看我是否可以扩展到这个最初的答案

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-26
      • 2016-04-15
      • 1970-01-01
      • 2014-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-21
      相关资源
      最近更新 更多