2017-03-16 12 views
1

DataFrameをそれ自身と結合する方法を理解する上で問題があります。具体的には、Columnの条件で結合の左右を参照してください。私はDataset.aliasが十分だと思ったが、私は間違っていなければならない、あるいは私の理解に何か他の不足がなければならない。説明するために:DataFrameを自分自身と結合して集約する方法

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

そのA

をなどのデータフレームを考えます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| 
// +---+-----+ 
// +---+-----+ 

、私は何を期待されていません。私は期待:

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| 
// +---+-----+ 
// | 1| 1| 
// | 3| 2| 
// | 5| 2| 
// | 4| 2| 
// | 2| 1| 
// +---+-----+ 

がやや少ない簡単な例を取るために

// +---+-----+ 
// | id|count| 
// +---+-----+ 
// | 5| 2| 
// | 4| 1| 
// | 2| 1| 
// +---+-----+ 

それは私には思える私はに必要なもの欠けていることpeople.valuesother.valuesを区別します。これどうやってするの?

私はあなたが彼らの完全修飾名を持つテーブルと参照列の両方のために、あなたがしなければならない等結合の別名使用しない限り、2.1

答えて

2

の火付け役、使用しています:people("id") =!= others("id")のような別名条件なしで

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")は些細なものであると考えられ、その結果です。