Nee*_*eel 41 scala apache-spark apache-spark-sql
我有两个包含以下列的数据框:
df1.columns
// Array(ts, id, X1, X2)
Run Code Online (Sandbox Code Playgroud)
和
df2.columns
// Array(ts, id, Y1, Y2)
Run Code Online (Sandbox Code Playgroud)
我之后
val df_combined = df1.join(df2, Seq(ts,id))
Run Code Online (Sandbox Code Playgroud)
我最终得到以下列:Array(ts, id, X1, X2, ts, id, Y1, Y2).我可以预期公共列将被删除.有什么额外的东西需要做吗?
sta*_*010 31
简单的答案(来自关于此问题的Databricks FAQ)是执行连接,其中连接列表示为字符串数组(或一个字符串)而不是谓词.
下面是一个改编自Databricks FAQ的示例,但有两个连接列,以回答原始海报的问题.
这是左侧数据帧:
val llist = Seq(("bob", "b", "2015-01-13", 4), ("alice", "a", "2015-04-23",10))
val left = llist.toDF("firstname","lastname","date","duration")
left.show()
/*
+---------+--------+----------+--------+
|firstname|lastname| date|duration|
+---------+--------+----------+--------+
| bob| b|2015-01-13| 4|
| alice| a|2015-04-23| 10|
+---------+--------+----------+--------+
*/
Run Code Online (Sandbox Code Playgroud)
这是正确的数据框:
val right = Seq(("alice", "a", 100),("bob", "b", 23)).toDF("firstname","lastname","upload")
right.show()
/*
+---------+--------+------+
|firstname|lastname|upload|
+---------+--------+------+
| alice| a| 100|
| bob| b| 23|
+---------+--------+------+
*/
Run Code Online (Sandbox Code Playgroud)
这是一个不正确的解决方案,其中连接列被定义为谓词left("firstname")===right("firstname") && left("lastname")===right("lastname").
不正确的结果是firstname和lastname列在连接的数据框中重复:
left.join(right, left("firstname")===right("firstname") &&
left("lastname")===right("lastname")).show
/*
+---------+--------+----------+--------+---------+--------+------+
|firstname|lastname| date|duration|firstname|lastname|upload|
+---------+--------+----------+--------+---------+--------+------+
| bob| b|2015-01-13| 4| bob| b| 23|
| alice| a|2015-04-23| 10| alice| a| 100|
+---------+--------+----------+--------+---------+--------+------+
*/
Run Code Online (Sandbox Code Playgroud)
的正确的解决方案是定义连接列作为一个字符串数组Seq("firstname", "lastname").输出数据框没有重复的列:
left.join(right, Seq("firstname", "lastname")).show
/*
+---------+--------+----------+--------+------+
|firstname|lastname| date|duration|upload|
+---------+--------+----------+--------+------+
| bob| b|2015-01-13| 4| 23|
| alice| a|2015-04-23| 10| 100|
+---------+--------+----------+--------+------+
*/
Run Code Online (Sandbox Code Playgroud)
zer*_*323 24
这是预期的行为.DataFrame.join方法相当于这样的SQL连接
SELECT * FROM a JOIN b ON joinExprs
Run Code Online (Sandbox Code Playgroud)
如果您想忽略重复的列,只需删除它们或之后选择感兴趣的列.如果您想消除歧义,可以使用父级访问这些DataFrames:
val a: DataFrame = ???
val b: DataFrame = ???
val joinExprs: Column = ???
a.join(b, joinExprs).select(a("id"), b("foo"))
// drop equivalent
a.alias("a").join(b.alias("b"), joinExprs).drop(b("id")).drop(a("foo"))
Run Code Online (Sandbox Code Playgroud)
或使用别名:
// As for now aliases don't work with drop
a.alias("a").join(b.alias("b"), joinExprs).select($"a.id", $"b.foo")
Run Code Online (Sandbox Code Playgroud)
对于equi-joins,存在一种特殊的快捷语法,它采用一系列字符串:
val usingColumns: Seq[String] = ???
a.join(b, usingColumns)
Run Code Online (Sandbox Code Playgroud)
或者作为单个字符串
val usingColumn: String = ???
a.join(b, usingColumn)
Run Code Online (Sandbox Code Playgroud)
它只保留连接条件中使用的列的一个副本.
我已经坚持了一段时间,直到最近我想出了一个非常简单的解决方案.
说是的
scala> val a = Seq(("a", 1), ("b", 2)).toDF("key", "vala")
a: org.apache.spark.sql.DataFrame = [key: string, vala: int]
scala> a.show
+---+----+
|key|vala|
+---+----+
| a| 1|
| b| 2|
+---+----+
and
scala> val b = Seq(("a", 1)).toDF("key", "valb")
b: org.apache.spark.sql.DataFrame = [key: string, valb: int]
scala> b.show
+---+----+
|key|valb|
+---+----+
| a| 1|
+---+----+
Run Code Online (Sandbox Code Playgroud)
我可以这样做只选择数据帧中的值a:
scala> a.join(b, a("key") === b("key"), "left").select(a.columns.map(a(_)) : _*).show
+---+----+
|key|vala|
+---+----+
| a| 1|
| b| 2|
+---+----+
Run Code Online (Sandbox Code Playgroud)
小智 6
尝试这个,
val df_combined = df1.join(df2, df1("ts") === df2("ts") && df1("id") === df2("id")).drop(df2("ts")).drop(df2("id"))
Run Code Online (Sandbox Code Playgroud)
你可以简单地使用这个
df1.join(df2, Seq("ts","id"),"TYPE-OF-JOIN")
Run Code Online (Sandbox Code Playgroud)
在这里TYPE-OF-JOIN可以是
例如,我有两个这样的数据框:
// df1
word count1
w1 10
w2 15
w3 20
// df2
word count2
w1 100
w2 150
w5 200
Run Code Online (Sandbox Code Playgroud)
如果您进行完全外部连接,则结果如下所示
df1.join(df2, Seq("word"),"fullouter").show()
word count1 count2
w1 10 100
w2 15 150
w3 20 null
w5 null 200
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
54028 次 |
| 最近记录: |