Apache spark Pyspark连接,然后列选择显示意外输出

Apache spark Pyspark连接,然后列选择显示意外输出,apache-spark,pyspark,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') 如你

我不确定长时间的工作是否对我有影响,但我在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.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|
+---+---+----+
如果我在其中一个数据帧上使用别名表达式,我会得到预期的行为

 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|
+---+---+----+
所以我的问题是,在联接之后选择列的最佳方式是什么?这种行为正常吗

编辑:根据用户8371915,这与标记为


但我的问题适用于两个具有相同血统的dataframe,它们在调用show方法时执行联接,但联接后的select列的行为不同

我能够复制你的发现,我希望我能回答为什么会发生这种情况。但是,我只需更改第二个(右侧)数据集的别名,就可以得到您想要的结果。我把mdf药物改成了mdf药物

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|
+---+---+-------+-----+

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

最好的方法是使用别名:

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也会从同一列返回值。

由于
df.col
df['col']
的结果是一个
类型,它不绑定到数据帧,因此我相信结果是预期的。我想知道为什么在错误的情况下选择时没有出现
不明确的列名
错误。通常,共享同一沿袭的
数据帧
之间的连接可能会导致轻微的真/假谓词。这个案子应该是自动处理的,但看起来事情好像是从裂缝中溜走了。诚实的建议-始终使用别名。可能重复的@user8371915看起来不像同一个问题。