数据框加入空安全条件使用

时间:2018-06-13 22:14:24

标签: python apache-spark dataframe pyspark apache-spark-sql

我有两个空值的数据框,我试图使用PySpark 2.3.0加入:

DFA:

# +----+----+
# |col1|col2|
# +----+----+
# |   a|null|
# |   b|   0|
# |   c|   0|
# +----+----+

DFB:

# +----+----+----+
# |col1|col2|col3|
# +----+----+----+
# |   a|null|   x|
# |   b|   0|   x|
# +----+----+----+

使用此脚本可以创建数据框:

dfA = spark.createDataFrame(
    [
        ('a', None),
        ('b', '0'),
        ('c', '0')
    ],
    ('col1', 'col2')
)

dfB = spark.createDataFrame(
    [
        ('a', None, 'x'),
        ('b', '0', 'x')
    ],
    ('col1', 'col2', 'col3')
)

加入电话:

dfA.join(dfB, dfB.columns[:2], how='left').orderBy('col1').show()

结果:

# +----+----+----+
# |col1|col2|col3|
# +----+----+----+
# |   a|null|null|  <- col3 should be x
# |   b|   0|   x|
# |   c|   0|null|
# +----+----+----+

预期结果:

# +----+----+----+
# |col1|col2|col3|
# +----+----+----+
# |   a|null|   x|  <-
# |   b|   0|   x|
# |   c|   0|null|
# +----+----+----+

如果我将第一行col2设置为null以外的任何值,那么它是有效的,但我需要支持null值。

我尝试使用条件进行比较,使用此post中概述的null-safe equals,如下所示:

cond = (dfA.col1.eqNullSafe(dfB.col1) & dfA.col2.eqNullSafe(dfB.col2))
dfA.join(dfB, cond, how='left').orderBy(dfA.col1).show()

null-safe join的结果:

# +----+----+----+----+----+
# |col1|col2|col1|col2|col3|
# +----+----+----+----+----+
# |   a|null|   a|null|   x|
# |   b|   0|   b|   0|   x|
# |   c|   0|null|null|null|
# +----+----+----+----+----+

这保留了重复的列,我仍然在寻找一种方法来在连接结束时达到预期的结果。

3 个答案:

答案 0 :(得分:3)

一个简单的解决方案是select要保留的列。这将允许您指定它们应来自哪个源数据帧,以及避免重复列问题。

dfA.join(dfB, cond, how='left').select(dfA.col1, dfA.col2, dfB.col3).orderBy('col1').show()

答案 1 :(得分:2)

此操作失败,因为col1中的orderBy不明确。您应该引用特定的来源,例如dfA

dfA.join(dfB, cond, how='left').orderBy(dfA.col1).show()

答案 2 :(得分:0)

如果你必须在pyspark中用空值连接空值,你应该在连接条件中使用eqnullsafe,然后将空值匹配到空值,spark 2.5版本之后最好使用eqnullsafe,如果需要更多示例{{ 3}}