Spark especifica múltiples condiciones de columna para unirse al marco de datos

Resuelto user568109 asked hace 9 años • 9 respuestas

Cómo dar más condiciones de columna al unir dos marcos de datos. Por ejemplo quiero ejecutar lo siguiente:

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")

Quiero unirme solo cuando estas columnas coincidan. Pero la sintaxis anterior no es válida ya que cols solo toma una cadena. Entonces, ¿cómo consigo lo que quiero?

user568109 avatar Jul 06 '15 14:07 user568109
Aceptado

Hay una unión API de columna/expresión de Spark para tal caso:

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"
)

El <=>operador en el ejemplo significa " Prueba de igualdad que es segura para valores nulos ".

La principal diferencia con la prueba de igualdad simple ( ===) es que la primera es segura de usar en caso de que una de las columnas tenga valores nulos.

rchukh avatar Jul 06 '2015 13:07 rchukh

A partir de la versión 1.5.0 de Spark (que actualmente no está publicada), puede unirse en varias columnas de DataFrame. Consulte SPARK-7990: Agregar métodos para facilitar la unión equivalente en múltiples claves de unión .

Pitón

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

escala

La pregunta pedía una respuesta de Scala, pero yo no uso Scala. Aquí está mi mejor suposición....

Leads.join(
    Utm_Master,
    Seq("LeadSource","Utm_Source","Utm_Medium","Utm_Campaign"),
    "left_outer"
)
dnlbrky avatar Aug 08 '2015 02:08 dnlbrky

Una cosa que puedes hacer es usar SQL sin formato:

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")
zero323 avatar Jul 06 '2015 10:07 zero323

Las ===opciones me dan columnas duplicadas. Entonces lo uso Seqen su lugar.

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

Por supuesto, esto sólo funciona cuando los nombres de las columnas que se unen son los mismos.

Climbs_lika_Spyder avatar Apr 13 '2018 17:04 Climbs_lika_Spyder