加入两个数据框,从一个列中选择所有列,从另一个列中选择一些列

Fra*_*mbo 50 pyspark pyspark-sql

假设我有一个火花数据帧df1,有几列(其中列'id')和数据帧df2有两列,'id'和'other'.

有没有办法复制以下命令

sqlContext.sql("SELECT df1.*, df2.other FROM df1 JOIN df2 ON df1.id = df2.id")
Run Code Online (Sandbox Code Playgroud)

通过仅使用诸如join(),select()之类的pyspark函数?

我必须在函数中实现此连接,并且我不希望强制将sqlContext作为函数参数.

谢谢!

max*_*nes 49

Asterisk(*)使用别名.例如:

from pyspark.sql.functions import *

df1 = df1.alias('df1')
df2 = df2.alias('df2')

df1.join(df2, df1.id == df2.id).select('df1.*')
Run Code Online (Sandbox Code Playgroud)

  • 完美-完整的解决方案; {df1.join(df2,df1.id == df2.id).select('df1。*','df2.other')}} (3认同)
  • 不知何故,这种方法对我来说在 Spark 3 上不起作用。 (3认同)

小智 48

不确定是否是最有效的方式,但这对我有用:

from pyspark.sql.functions import col

df1.alias('a').join(df2.alias('b'),col('b.id') == col('a.id')).select([col('a.'+xx) for xx in a.columns] + [col('b.other1'),col('b.other2')])
Run Code Online (Sandbox Code Playgroud)

诀窍是:

[col('a.'+xx) for xx in a.columns] : all columns in a

[col('b.other1'),col('b.other2')] : some columns of b
Run Code Online (Sandbox Code Playgroud)

  • 在spark2中,我不得不将其更改为col('b.id')== col('a.id')(带有两个等号).否则,它会给我一个'SyntaxError:关键字不能是表达式'异常 (5认同)

小智 14

不使用别名。

df1.join(df2, df1.id == df2.id).select(df1["*"],df2["other"])
Run Code Online (Sandbox Code Playgroud)

  • 我注意到,当连接的数据帧具有相同名称的列名称时,在 select 方法中执行 `df1["*"]` 可以正确地从该数据帧中获取列,即使 `df2` 具有某些与 `df1` 名称相同的列。您介意解释一下(或链接到相关文档)这是如何工作的吗? (2认同)
  • 恕我直言,这是当前(2022 年)最佳答案 (2认同)

Kat*_*ler 10

这是一个不需要SQL上下文但保留DataFrame元数据的解决方案.

a = sc.parallelize([['a', 'foo'], ['b', 'hem'], ['c', 'haw']]).toDF(['a_id', 'extra'])
b = sc.parallelize([['p1', 'a'], ['p2', 'b'], ['p3', 'c']]).toDF(["other", "b_id"])

c = a.join(b, a.a_id == b.b_id)
Run Code Online (Sandbox Code Playgroud)

然后,c.show()收益率:

+----+-----+-----+----+
|a_id|extra|other|b_id|
+----+-----+-----+----+
|   a|  foo|   p1|   a|
|   b|  hem|   p2|   b|
|   c|  haw|   p3|   c|
+----+-----+-----+----+
Run Code Online (Sandbox Code Playgroud)

  • 好吧,OP 要求只选择几个 cols,即。过滤,答案包含连接后的所有列。 (4认同)

小智 6

我相信这将是最简单和最直观的方法:

final = (df1.alias('df1').join(df2.alias('df2'),
                               on = df1['id'] == df2['id'],
                               how = 'inner')
                         .select('df1.*',
                                 'df2.other')
)
Run Code Online (Sandbox Code Playgroud)


小智 5

删除重复的 b_id

c = a.join(b, a.a_id == b.b_id).drop(b.b_id)
Run Code Online (Sandbox Code Playgroud)