这是预期的行为吗?我想提出Spark的一个问题,但这似乎是一个基本的功能,很难想象这里有一个bug。我错过了什么?
蟒蛇
import numpy as np
>>> np.nan < 0.0
False
>>> np.nan > 0.0
False
PySpark
from pyspark.sql.functions import col
df = spark.createDataFrame([(np.nan, 0.0),(0.0, np.nan)])
df.show()
#+---+---+
#| _1| _2|
#+---+---+
#|NaN|0.0|
#|0.0|NaN|
#+---+---+
df.printSchema()
#root
# |-- _1: double (nullable = true)
# |-- _2: double (nullable = true)
df.select(col("_1")> col("_2")).show()
#+---------+
#|(_1 > _2)|
#+---------+
#| true|
#| false|
#+---------+
这是预期和记录的行为。引用官方NaN Semantics(强调我的)的Spark SQL Guide部分:
在处理与标准浮点语义不完全匹配的float或double类型时,对not-a-number(NaN)进行了特殊处理。特别:
- Nun = Nun Radurns Tru。
- 在聚合中,所有NaN值都组合在一起。
- NaN在连接键中被视为正常值。
- NaN值按升序排列,大于任何其他数值。
与Python NaN相比,AdAs你看到排序行为不是唯一的区别。特别是Spark认为NaN是平等的:
spark.sql("""
WITH table AS (SELECT CAST('NaN' AS float) AS x, cast('NaN' AS float) AS y)
SELECT x = y, x != y FROM table
""").show()
+-------+-------------+
|(x = y)|(NOT (x = y))|
+-------+-------------+
| true| false|
+-------+-------------+
而普通的Python
float("NaN") == float("NaN"), float("NaN") != float("NaN")
(False, True)
和NumPy
np.nan == np.nan, np.nan != np.nan
(False, True)
别。
您可以查看eqNullSafe
docstring以获取更多示例。
因此,要获得所需的结果,您必须明确检查NaN的结果
from pyspark.sql.functions import col, isnan, when
when(isnan("_1") | isnan("_2"), False).otherwise(col("_1") > col("_2"))