如何将数据帧与自身联接并聚合



我很难理解如何用自身连接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.valuesother.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") 这样的条件被认为是微不足道的错误,因此结果。

相关内容

  • 没有找到相关文章

最新更新