PySpark 中字符串与空值比较的结果难以理解
Incomprehensible result of a comparison between a string and null value in PySpark
任何人都可以向我解释字符串和空值之间比较的行为。
数据帧:
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
值(如果可能)的情况下解决这个问题。
之所以得到equal
与null比较是因为text1 != null
给出的是null,被when
语句解释为false,所以得到了意想不到的equal
来自 otherwise
语句。
您可以使用 eqNullSafe
,当其中一列为 null 时,returns 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|
+------+------+---------+
NULL
不是数值而是代表没有数值。您不能将它与一个值或另一个 null 进行比较,该比较在 if
、when
函数中始终被解释为 false。对于 null 安全相等检查,您还可以使用 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")
)
任何人都可以向我解释字符串和空值之间比较的行为。
数据帧:
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
值(如果可能)的情况下解决这个问题。
之所以得到equal
与null比较是因为text1 != null
给出的是null,被when
语句解释为false,所以得到了意想不到的equal
来自 otherwise
语句。
您可以使用 eqNullSafe
,当其中一列为 null 时,returns 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|
+------+------+---------+
NULL
不是数值而是代表没有数值。您不能将它与一个值或另一个 null 进行比较,该比较在 if
、when
函数中始终被解释为 false。对于 null 安全相等检查,您还可以使用 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")
)