web-dev-qa-db-ja.com

Sparkは、データフレーム結合の複数の列条件を指定します

2つのデータフレームを結合するときに列条件を増やす方法。たとえば、私は次を実行したい:

val Lead_all = Leads.join(Utm_Master,  
    Leaddetails.columns("LeadSource","Utm_Source","Utm_Medium","Utm_Campaign") ==
    Utm_Master.columns("LeadSource","Utm_Source","Utm_Medium","Utm_Campaign"),
"left")

これらの列が一致する場合にのみ参加したい。しかし、colsは1つの文字列しか受け取れないため、上記の構文は無効です。だから私はどのように私が欲しいものを手に入れるのですか?.

43
user568109

このような場合、Spark 列/式API結合 があります。

Leaddetails.join(
    Utm_Master, 
    Leaddetails("LeadSource") <=> Utm_Master("LeadSource")
        && Leaddetails("Utm_Source") <=> Utm_Master("Utm_Source")
        && Leaddetails("Utm_Medium") <=> Utm_Master("Utm_Medium")
        && Leaddetails("Utm_Campaign") <=> Utm_Master("Utm_Campaign"),
    "left"
)

例の<=>演算子は、「 null値に対して安全な等価テスト 」を意味します。

単純な 等価テスト===)との主な違いは、最初の列は、列の1つにnull値が含まれる場合に安全に使用できることです。

75
rchukh

Sparkバージョン1.5.0(現在未リリース)の時点で、複数のDataFrame列に参加できます。 SPARK-7990:複数の結合キーでの等結合を容易にするメソッドを追加 を参照してください。

Python

Leads.join(
    Utm_Master, 
    ["LeadSource","Utm_Source","Utm_Medium","Utm_Campaign"],
    "left_outer"
)

スカラ

質問はScalaの回答を求めましたが、私はScalaを使用していません。これが私の最良の推測です...

Leads.join(
    Utm_Master,
    Seq("LeadSource","Utm_Source","Utm_Medium","Utm_Campaign"),
    "left_outer"
)
15
dnlbrky

できることの1つは、生のSQLを使用することです。

case class Bar(x1: Int, y1: Int, z1: Int, v1: String)
case class Foo(x2: Int, y2: Int, z2: Int, v2: String)

val bar = sqlContext.createDataFrame(sc.parallelize(
    Bar(1, 1, 2, "bar") :: Bar(2, 3, 2, "bar") ::
    Bar(3, 1, 2, "bar") :: Nil))

val foo = sqlContext.createDataFrame(sc.parallelize(
    Foo(1, 1, 2, "foo") :: Foo(2, 1, 2, "foo") ::
    Foo(3, 1, 2, "foo") :: Foo(4, 4, 4, "foo") :: Nil))

foo.registerTempTable("foo")
bar.registerTempTable("bar")

sqlContext.sql(
    "SELECT * FROM foo LEFT JOIN bar ON x1 = x2 AND y1 = y2 AND z1 = z2")
7
zero323

Pysparkでは、各条件を個別に指定できます。

val Lead_all = Leads.join(Utm_Master,  
    (Leaddetails.LeadSource == Utm_Master.LeadSource) &
    (Leaddetails.Utm_Source == Utm_Master.Utm_Source) &
    (Leaddetails.Utm_Medium == Utm_Master.Utm_Medium) &
    (Leaddetails.Utm_Campaign == Utm_Master.Utm_Campaign))

必ず演算子と括弧を正しく使用してください。

6
Patricia F.

スカラ:

Leaddetails.join(
    Utm_Master, 
    Leaddetails("LeadSource") <=> Utm_Master("LeadSource")
        && Leaddetails("Utm_Source") <=> Utm_Master("Utm_Source")
        && Leaddetails("Utm_Medium") <=> Utm_Master("Utm_Medium")
        && Leaddetails("Utm_Campaign") <=> Utm_Master("Utm_Campaign"),
    "left"
)

大文字と小文字を区別しないようにするために

import org.Apache.spark.sql.functions.{lower, upper}

次に、結合メソッドの条件でlower(value)を使用します。

例:dataFrame.filter(lower(dataFrame.col("vendor")).equalTo("fortinet"))

5
Ani Menon

===オプションにより、重複した列が表示されます。そこで、代わりにSeqを使用します。

val Lead_all = Leads.join(Utm_Master,
    Seq("Utm_Source","Utm_Medium","Utm_Campaign"),"left")

もちろん、これは、結合する列の名前が同じ場合にのみ機能します。

2

これを試して:

val rccJoin=dfRccDeuda.as("dfdeuda")
.join(dfRccCliente.as("dfcliente")
,col("dfdeuda.etarcid")===col("dfcliente.etarcid") 
&& col("dfdeuda.etarcid")===col("dfcliente.etarcid"),"inner")
0
Andy Quiroz

Spark SQLは、次のように、括弧内の列のタプルでの結合をサポートします

... WHERE (list_of_columns1) = (list_of_columns2)

これは、一連の "AND"で結合された列の各ペアに等しい式(=)を指定するよりもずっと短い方法です。

例えば:

SELECT a,b,c
FROM    tab1 t1
WHERE 
   NOT EXISTS
   (    SELECT 1
        FROM    t1_except_t2_df e
        WHERE (t1.a, t1.b, t1.c) = (e.a, e.b, e.c)
   )

の代わりに

SELECT a,b,c
FROM    tab1 t1
WHERE 
   NOT EXISTS
   (    SELECT 1
        FROM    t1_except_t2_df e
        WHERE t1.a=e.a AND t1.b=e.b AND t1.c=e.c
   )

特に列のリストが大きく、NULLを簡単に処理したい場合は、読みにくくなります。

0
Tagar