Pyspark加入然后列选择显示意外输出

时间:2018-06-06 22:43:56

标签: apache-spark pyspark

我不确定长时间的工作是否对我这么做但是我在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方法时执行连接的数据框但是连接后的选择列的行为方式不同。

2 个答案:

答案 0 :(得分:3)

最好的方法是使用别名:

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.drugmdf.drug都引用同一列。因此,当您将它们传递给select时,Spark也会返回同一列中的值。

答案 1 :(得分:1)

我能够复制你的发现,我希望我能回答为什么会这样。但是,通过更改第二个(右侧)数据集的别名,我能够获得所需的结果。我将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|
+---+---+-------+-----+

我将进行更多研究,看看我是否可以扩展到这个初步答案