pyspark中字符串和空值之间比较的不可理解的结果

zc0qhyus  于 2021-07-13  发布在  Spark
关注(0)|答案(2)|浏览(318)

有人能解释一下字符串和空值之间的比较行为吗。
Dataframe:

import pyspark.sql.functions as F

df = spark.createDataFrame([
["text_1,","text_1"],
["text_1,","text_2"],
["text_1,",None]
]).toDF("col1", "col2")

df1 = df.withColumn("equal", F.when(F.col("col1") == F.col("col2"), "equal").otherwise("not equal")

+-------+-------+----------+
|col1   |col2   |equal     |
+-------+-------+----------+
|text_1 |text_1 |equal     |
|text_1 |text_2 |not equal |
|text_1 |null   |not equal |  <*
+-------+-------+----------+

df2 = df.withColumn("equal", F.when(F.col("col1") != F.col("col2"), "equal").otherwise("not equal")

+-------+-------+----------+
|col1   |col2   |equal     |
+-------+-------+----------+
|text_1 |text_1 |equal     |
|text_1 |text_2 |not equal |
|text_1 |null   |equal     |   <*
+-------+-------+----------+

这个 is equal 比较起来似乎很顺利,但是 is not equal 出了问题。
有人能给我解释一下吗?我怎么能不检查就解决这个问题呢 .isNotNull 或填充 null 带有空字符串的值(如果可能)。

sczxawaw

sczxawaw1#

你为什么 equal 与null比较是因为 text1 != null 提供null,由 when 声明,所以你得到了意想不到的结果 equalotherwise 声明。
你可以用 eqNullSafe ,当其中一列为null时,返回false而不是null。如果你想比较不等式,就用否定 ~eqNullSafe .

import pyspark.sql.functions as F

df3 = df.withColumn("equal",
    F.when(~F.col("col1").eqNullSafe(F.col("col2")), "not equal")
     .otherwise("equal")
)

df3.show()
+------+------+---------+
|  col1|  col2|    equal|
+------+------+---------+
|text_1|text_1|    equal|
|text_1|text_2|not equal|
|text_1|  null|not equal|
+------+------+---------+

如果要用空字符串填充空值,可以使用 coalesce :

import pyspark.sql.functions as F

df4 = df.withColumn("equal",
    F.when(F.col("col1") != F.coalesce(F.col("col2"), F.lit("")), "not equal")
     .otherwise("equal")
)

df4.show()
+------+------+---------+
|  col1|  col2|    equal|
+------+------+---------+
|text_1|text_1|    equal|
|text_1|text_2|not equal|
|text_1|  null|not equal|
+------+------+---------+
mnowg1ta

mnowg1ta2#

NULL 不是价值而是代表价值的缺失。不能将其与值或另一个空值进行比较,比较在中总是被解释为false if , when 功能。对于空安全相等检查,还可以使用sql表达式 is distinct from :

from pyspark.sql import functions as F

df1 = df.withColumn(
    "equal",
    F.when(
        F.expr("col1 is distinct from col2"), "not equal"
    ).otherwise("equal")
)

df1.show()

# +------+------+---------+

# |  col1|  col2|    equal|

# +------+------+---------+

# |text_1|text_1|    equal|

# |text_1|text_2|not equal|

# |text_1|  null|not equal|

# +------+------+---------+

或使用 <=> 操作员:

df1 = df.withColumn(
    "equal",
    F.when(
        ~F.expr("col1 <=> col2"), "not equal"
    ).otherwise("equal")
)

相关问题