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つの文字列しか受け取れないため、上記の構文は無効です。だから私はどのように私が欲しいものを手に入れるのですか?.
このような場合、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値が含まれる場合に安全に使用できることです。
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"
)
できることの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")
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))
必ず演算子と括弧を正しく使用してください。
スカラ:
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"))
===
オプションにより、重複した列が表示されます。そこで、代わりにSeq
を使用します。
val Lead_all = Leads.join(Utm_Master,
Seq("Utm_Source","Utm_Medium","Utm_Campaign"),"left")
もちろん、これは、結合する列の名前が同じ場合にのみ機能します。
これを試して:
val rccJoin=dfRccDeuda.as("dfdeuda")
.join(dfRccCliente.as("dfcliente")
,col("dfdeuda.etarcid")===col("dfcliente.etarcid")
&& col("dfdeuda.etarcid")===col("dfcliente.etarcid"),"inner")
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を簡単に処理したい場合は、読みにくくなります。