При динамическом создании условия соединения в виде списка в PySpark, как применить «ИЛИ» между элементами вместо «И»? - PullRequest
0 голосов
/ 05 августа 2020

Я присоединяюсь к двум фреймам данных site_bs и site_wrk_int1 и создаю site_wrk, используя динамическое c условие соединения.

Мой код выглядит следующим образом: * и значение будет примерно таким: [col (id) == col (wrk_id), col (id) == col (wrk_parentId)] * ​​1006 *

В приведенном выше условии соединения соединение будет выполняться при соблюдении обоих условий выше. т.е. условие соединения будет

id = wrk_id  and id = wrk_parentId 

Но я хочу, чтобы или условие применялось, как показано ниже

id = wrk_id  or id = wrk_parentId 

Как этого добиться в Pyspark?

Ответы [ 2 ]

0 голосов
/ 05 августа 2020

Поскольку логические операции с pyspark столбцами возвращают объекты столбцов, вы можете связать эти условия в операторе соединения, например:

from pyspark.sql import SparkSession
import pyspark.sql.functions as f


spark = SparkSession.builder.getOrCreate()

df = spark.createDataFrame([
    (1, "A", "A"),
    (2, "C", "C"), 
    (3, "E", "D"), 
], ['id', 'col1', 'col2'] 
)
df.show()
+---+----+----+
| id|col1|col2|
+---+----+----+
|  1|   A|   A|
|  2|   C|   C|
|  3|   E|   D|
+---+----+----+


df.alias("t1").join(
    df.alias("t2"),
    (f.col("t1.col1") == f.col("t2.col2")) | (f.col("t1.col1") == f.lit("E")),
    "left_outer"
).show(truncate=False)
+---+----+----+---+----+----+
|id |col1|col2|id |col1|col2|
+---+----+----+---+----+----+
|1  |A   |A   |1  |A   |A   |
|2  |C   |C   |2  |C   |C   |
|3  |E   |D   |1  |A   |A   |
|3  |E   |D   |2  |C   |C   |
|3  |E   |D   |3  |E   |D   |
+---+----+----+---+----+----+

Как видите, я получаю значение True для left строки с идентификаторами 1 и 2 как col1 == col2 OR col1 == E, что равно True для трех строк моего DataFrame. С точки зрения синтаксиса важно, чтобы операторы Python (| & ...) были разделены закрытыми скобками, как в приведенном выше примере, иначе вы можете запутаться в ошибках py4j.

В качестве альтернативы, если вы sh, чтобы сохранить такую ​​же нотацию, как вы указали в своих вопросах, почему бы не использовать functools.reduce и operator.or_ для применения этого logi c к вашему списку, например:

В этом примере у меня есть условие AND между условиями моего столбца и получение только NULL, как и ожидалось:

df.alias("t1").join(
    df.alias("t2"),
    [f.col("t1.col1") == f.col("t2.col2"),  f.col("t1.col1") == f.lit("E")],
    "left_outer"
).show(truncate=False)
+---+----+----+----+----+----+
|id |col1|col2|id  |col1|col2|
+---+----+----+----+----+----+
|3  |E   |D   |null|null|null|
|1  |A   |A   |null|null|null|
|2  |C   |C   |null|null|null|
+---+----+----+----+----+----+

В этом примере я использую functools и operator, чтобы получить тот же результат, что и выше:

df.alias("t1").join(
    df.alias("t2"),
    functools.reduce(
      operator.or_, 
      [f.col("t1.col1") == f.col("t2.col2"),  f.col("t1.col1") == f.lit("E")]),
    "left_outer"
).show(truncate=False)
+---+----+----+---+----+----+
|id |col1|col2|id |col1|col2|
+---+----+----+---+----+----+
|1  |A   |A   |1  |A   |A   |
|2  |C   |C   |2  |C   |C   |
|3  |E   |D   |1  |A   |A   |
|3  |E   |D   |2  |C   |C   |
|3  |E   |D   |3  |E   |D   |
+---+----+----+---+----+----+
0 голосов
/ 05 августа 2020

Я новичок в Spark SQL. Сообщите мне, возможно ли это решение.

site_wrk = site_bs.join(site_work_int1, [(site_bs.id == site_work_int1.wrk_id) | (site_bs.id == site_work_int1.wrk_parentId)], how = "inner")
...