【问题标题】:Comparison of a `float` to `np.nan` in Spark DataframeSpark Dataframe 中“float”与“np.nan”的比较
【发布时间】:2019-08-09 04:34:55
【问题描述】:

这是预期的行为吗?我想提出一个关于 Spark 的问题,但这似乎是一个基本的功能,很难想象这里有一个错误。我错过了什么?

Python

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|
#+---------+

【问题讨论】:

  • 似乎他们正在使用类似 Double.compare 的东西在存在 NaN 的情况下进行排序,导致您看到 true 值,但我没有找到任何关于这件事。

标签: python numpy apache-spark pyspark nan


【解决方案1】:

这是预期和记录的行为。引用官方Spark SQL GuideNaN Semantics部分(强调我的):

在处理与标准浮点语义不完全匹配的浮点或双精度类型时,对非数字 (NaN) 进行了特殊处理。具体来说:

  • NaN = NaN 返回真。
  • 在聚合中,所有 NaN 值都组合在一起。
  • NaN 在连接键中被视为正常值。
  • NaN 值在升序时排在最后,大于任何其他数值

Ad正如您所见,与 Python NaN 相比,排序行为并不是唯一的区别。特别是 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"))

【讨论】:

  • np.nanfloat("NaN") - 它们不是一回事吗(即使它们在技术上并不相等)?
猜你喜欢
  • 2018-10-03
  • 2017-07-12
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-29
相关资源
最近更新 更多