Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:排序函数在nan出现时中断_Python_Math_Sorting_Nan - Fatal编程技术网

Python:排序函数在nan出现时中断

Python:排序函数在nan出现时中断,python,math,sorting,nan,Python,Math,Sorting,Nan,sorted([2,float('nan'),1])返回[2,nan,1] (至少在Activestate Python 3.1实现上是如此。) 我知道nan是一个奇怪的对象,所以如果它出现在排序结果中的随机位置,我不会感到惊讶。但它也会弄乱容器中非nan数字的排序,这真是出乎意料 我问了一个关于max的问题,基于此我理解了sort为什么会这样工作。但这应该被视为一个bug吗 文档只是说“返回一个新的排序列表[…]”,没有指定任何细节 编辑: 我现在同意这没有违反IEEE标准。然而,我认为,从任

sorted([2,float('nan'),1])
返回
[2,nan,1]

(至少在Activestate Python 3.1实现上是如此。)

我知道
nan
是一个奇怪的对象,所以如果它出现在排序结果中的随机位置,我不会感到惊讶。但它也会弄乱容器中非nan数字的排序,这真是出乎意料

我问了一个关于
max
的问题,基于此我理解了
sort
为什么会这样工作。但这应该被视为一个bug吗

文档只是说“返回一个新的排序列表[…]”,没有指定任何细节

编辑: 我现在同意这没有违反IEEE标准。然而,我认为,从任何常识的角度来看,这都是一个缺陷。即使是不常承认错误的微软,也已将这一错误视为一个bug,并在最新版本中修复了它:

无论如何,我最终还是按照@khachik的回答:

sorted(list_, key = lambda x : float('-inf') if math.isnan(x) else x)

与默认情况下使用的语言相比,我怀疑它会导致性能下降,但至少它是有效的(除非我引入了任何bug)。

IEEE754是在这种情况下定义浮点操作的标准。本标准将操作数的比较运算(其中至少有一个是NaN)定义为错误。因此,这不是一个bug。在对阵列进行操作之前,您需要处理NAN。

我不确定该错误,但解决方法可能是:

sorted(
    (2, 1, float('nan')),
    lambda x,y: x is float('nan') and -1 
                or (y is float('nan') and 1
                or cmp(x,y)))
其结果是:

('nan', 1, 2)

或者在排序或其他任何操作之前删除
nan
s。

问题在于,如果列表包含nan,则没有正确的顺序,因为序列a1、a2、a3,…,如果a1前面的答案有用,则会对an进行排序,但可能不清楚问题的根源


在任何语言中,sort都在输入值的域上应用给定的顺序,该顺序由比较函数或以其他方式定义。例如,小于,a.k.a.
运算符假设您希望保留nan并将其作为最低“值”排序,这里有一个解决方案,可同时处理非唯一nan、唯一numpy nan、数字和非数字对象:


无论采用何种标准,在许多情况下,用户定义的浮点值和
NA
值顺序都是有用的。例如,我在对股票收益进行排序,希望使用
NA
last从高到低排序(因为这些都是不相关的)。有4种可能的组合

from functools import partial

a = [2, float('nan'), 1]
sorted(a, key=sort_with_na)                                         # Default
sorted(a, key=partial(sort_with_na, reverse=False, na_last=True))   # Ascend, NA last
sorted(a, key=partial(sort_with_na, reverse=False, na_last=False))  # Ascend, NA first
sorted(a, key=partial(sort_with_na, reverse=True, na_last=True))    # Descend, NA last
sorted(a, key=partial(sort_with_na, reverse=True, na_last=False))   # Descend, NA first
  • 升序浮点值,
    NA
    最后一个值
  • 升序浮点值,
    NA
    先值
  • 浮点值递减,
    NA
    最后一个值
  • 从浮点值开始递减,
    NA
    先值
  • 这是一个通过有条件地将
    NA
    值替换为
    +/-inf

    import math 
    
    def sort_with_na(x, reverse=False, na_last=True):
        """Intelligently sort iterable with NA values
    
        For reliable behavior with NA values, we should change the NAs to +/- inf
        to guarantee their order rather than relying on the built-in
        ``sorted(reverse=True)`` which will have no effect. To use the ``reverse``
        parameter or other kwargs, use functools.partial in your lambda i.e.
    
            sorted(iterable, key=partial(sort_with_na, reverse=True, na_last=False))
    
        :param x: Element to be sorted
        :param bool na_last: Whether NA values should come last or first
        :param bool reverse: Return ascending if ``False`` else descending
        :return bool:
        """
        if not math.isnan(x):
            return -x if reverse else x
        else:
            return float('inf') if na_last else float('-inf')
    
    测试4种组合中的每一种

    from functools import partial
    
    a = [2, float('nan'), 1]
    sorted(a, key=sort_with_na)                                         # Default
    sorted(a, key=partial(sort_with_na, reverse=False, na_last=True))   # Ascend, NA last
    sorted(a, key=partial(sort_with_na, reverse=False, na_last=False))  # Ascend, NA first
    sorted(a, key=partial(sort_with_na, reverse=True, na_last=True))    # Descend, NA last
    sorted(a, key=partial(sort_with_na, reverse=True, na_last=False))   # Descend, NA first
    

    弹性排序涉及比较两个项目并返回:更少、相等、更大

    如果
    cmp(a,b)
    为“较大”,则
    cmp(b,a)
    必须为“较小”

    如果
    cmp(a,b)
    为“零”,则
    cmp(b,a)
    必须为“零”

    到目前为止,答案中缺少的是比较2
    float
    s的情况,这两个都是s并保留了上述属性。2 NAN应根据其有效载荷的一致解释进行同等或可能的比较

    替换比较算法以放置所有NAN>+inf

    if isnan(a)
      if isnan(b)
        return 0 (or maybe compare payloads/bit patterns)
      return 1
    if isnan(b) return 1
    if a > b return 1
    if a < b return -1
    return 0
    
    如果isnan(a)
    如果isnan(b)
    返回0(或者可能比较有效负载/位模式)
    返回1
    如果isnan(b)返回1
    如果a>b,则返回1
    如果a
    非数字(NAN)对于数字排序或任何需要数字的输入无效;所以我不认为这是一个错误。”弗莱瑟:这不太正确。它在Python中无效吗?否,因为Python不会引发异常。它在IEEE754中无效吗?否,因为它提供了非常具体的行为(至少对于安静的
    nan
    )。它在其他一些标准中无效吗?虽然可以理解“nan”将在结果列表中的某个位置随机结束,但更难理解的是,显然错误地排列仍然在最后的数值是正确的行为:排序([1.0,2.0,3.0,float('nan'),4.0,3.0,2.0,1.0])=>[1.0,2.0,3.0,nan,1.0,2.0,3.0,4.0].See.-1 Python不遵循IEEE754,IEEE754要求有两个nan:信令和非信令,以及两个比较运算符:信令和非信令。此外,IEEE754-2008特别要求与
    nan
    进行比较时
    max
    返回数字。如果是信令nan(sNaN)然后硬件将引发异常。对于安静的NaN(qNaN)硬件不会引发异常,如果期望每个处理浮点值的库例程都检查QNaN,那就太麻烦了。如果您在一台FP硬件基于IEEE754的机器上运行CPython,那么这就是您将得到的结果。另外,IEEE754在什么意义上定义了max?Python文档中有这样的内容关于IEEE754:“今天(2010年7月)几乎所有的机器都使用IEEE-754浮点运算,几乎所有的平台都将Python浮点映射到IEEE-754“双精度”另外,非常感谢你的否决票。仅仅因为你不喜欢答案并不意味着你就应该杀了messenger!!;-)@max我们可以随心所欲地争论,但事实就是这样,你只需要预处理阵列并检查NAN-如果你不喜欢它的处理方式,那么你就必须与Guido合作!!!IEEE 754不需要hat max(NaN,1)返回1。如果Python遵循标准,那就好了,但它没有。如果它遵循自己的规则,它至少可以有一些合理的规则,而不是随机的不稳定行为。为了澄清,我同意您的看法,
    float('NaN')<1或float('NaN')>=1
    应该返回False。似乎异常有b