You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

为何sorted()无法排序含nan的NumPy数组?能否实现该排序?

为什么sorted()无法排序含NaN的NumPy数组?能否用sorted()实现该排序?

这问题问得很到位!我来给你掰扯清楚里面的门道:

一、为什么内置sorted()搞不定含NaN的数组?

核心原因在于NaN的比较特性和Python内置排序的逻辑:

  • 根据IEEE 754浮点标准,NaN(Not a Number)和任何值(包括它自己)的比较结果都是False。比如nan < 2False2 < nan也是False,甚至nan == nan还是False
  • Python的sorted()依赖元素之间的全序关系(简单说就是任意两个元素都能明确分出大小),但NaN打破了这个规则——排序算法根本不知道该把NaN放在哪个位置,因为它和任何元素都“比不出结果”。
  • 最终的表现就是:NaN会维持在原数组中的相对位置,其他元素的排序也会因为和NaN的无效比较而混乱,就像你看到的例子那样,[nan,2,nan,1]sorted()处理后还是[nan, 2.0, nan, 1.0],完全没排好。

二、为什么NumPy的values.sort()能行?

NumPy自己实现了一套专门的排序逻辑,它主动给NaN设定了排序规则:默认情况下,NumPy会把NaN视为“比所有数值都大”的元素,排序时自动把它们放到数组末尾,而正常数值则按常规逻辑排序,所以你看到的结果是[1. 2. nan nan]

三、能用sorted()实现含NaN数组的排序吗?必须可以!

只需要给sorted()传入自定义的key函数,给NaN指定一个明确的排序优先级就行。这里有两种常用的写法:

方法1:用布尔值区分NaN和正常数值

import numpy as np
values = np.array([float('nan'),2,float('nan'),1],dtype=float)
# 让非NaN元素排在前面,内部按数值排序;NaN排到最后
values_sorted = sorted(values, key=lambda x: (np.isnan(x), x))
print(values_sorted)
# 输出: [1.0, 2.0, nan, nan]

原理:lambda返回的元组中,第一个元素是np.isnan(x)(NaN为True,非NaN为False),因为False < True,所以非NaN元素会全部排在NaN前面;第二个元素是x本身,保证非NaN元素按正常大小排序。如果想把NaN放最前面,把np.isnan(x)改成not np.isnan(x)就行。

方法2:用无穷大/无穷小作为NaN的排序键

# 把NaN的键设为无穷大,让它们排到最后
values_sorted = sorted(values, key=lambda x: float('inf') if np.isnan(x) else x)
# 如果想让NaN排最前面,就用负无穷:float('-inf')

这个逻辑更直观:直接给NaN分配一个极端值的键,让排序算法明确知道该把它们放在哪里。


内容的提问来源于stack exchange,提问作者MakotoE

火山引擎 最新活动