我很难理解如何用自身连接DataFrame
,并在Column
条件中专门引用连接的左侧和右侧。我以为Dataset.alias
就足够了,但我一定是错了,或者我的理解一定有其他的不足。举例说明:
给定一个数据帧,如下所示:
val people = Seq((1,"foo",11),(2,"foo",12),(3,"bar",23),(4,"bar",24),(5,"bar",25),(6,"zap",36)).toDF("id","group","number")
people.show()
// +---+-----+------+
// | id|group|number|
// +---+-----+------+
// | 1| foo| 11|
// | 2| foo| 12|
// | 3| bar| 23|
// | 4| bar| 24|
// | 5| bar| 25|
// | 6| zap| 36|
// +---+-----+------+
如果我想知道任何给定 id 的每个组有多少条目,我可能会这样做:
val others = people.alias("others")
val peopleInGroup = (
people
.join(others, people("group") === others("group"), "left_outer")
.groupBy(people("id"))
)
peopleInGroup.count().show()
// +---+-----+
// | id|count|
// +---+-----+
// | 1| 2|
// | 6| 1|
// | 3| 3|
// | 5| 3|
// | 4| 3|
// | 2| 2|
// +---+-----+
ids的顺序发生了变化有点令人担忧,但计数值是我所期望的;到目前为止一切顺利。
如果我想知道每个组还有多少其他条目,我可能会这样做:
val othersInGroup = (
people
.join(others, people("group") === others("group"), "left_outer")
.filter(people("id") =!= others("id"))
.groupBy(people("id"))
)
othersInGroup.count().show()
// +---+-----+
// | id|count|
// +---+-----+
// +---+-----+
,这不是我所期望的。我期望:
// +---+-----+
// | id|count|
// +---+-----+
// | 1| 1|
// | 3| 2|
// | 5| 2|
// | 4| 2|
// | 2| 1|
// +---+-----+
举一个稍微不那么微不足道的例子:
val otherWithLowerNumber = (
people
.join(others, people("group") === others("group"), "left_outer")
.filter(people("number") > others("number"))
.groupBy(people("id"))
)
otherWithLowerNumber.count().show()
// +---+-----+
// | id|count|
// +---+-----+
// +---+-----+
我期望:
// +---+-----+
// | id|count|
// +---+-----+
// | 5| 2|
// | 4| 1|
// | 2| 1|
// +---+-----+
在我看来,我错过了区分people.values
和other.values
所需的东西.我该怎么做?
我正在使用Spark 2.1
除非使用 equi-joins,否则应使用其完全限定名为表和引用列设置别名:
import spark.implicits._
people.alias("people")
// Equi-join by name could be replaced with
// $"people.group" === $"others.group"
.join(others, Seq("group"), "left_outer")
.where($"people.id" =!= $"others.id")
.groupBy($"people.id")
.count
+---+-----+
| id|count|
+---+-----+
| 1| 1|
| 3| 2|
| 5| 2|
| 4| 2|
| 2| 1|
+---+-----+
如果没有别名,像 people("id") =!= others("id")
或 people("id") > others("id")
这样的条件被认为是微不足道的错误,因此结果。