Python:使用 NaN 对数组进行排序
Posted
技术标签:
【中文标题】Python:使用 NaN 对数组进行排序【英文标题】:Python: sorting an array with NaNs 【发布时间】:2014-02-06 23:58:23 【问题描述】:注意:我使用的是 Python 和 numpy 数组。
我有很多数组,它们都有两列和多行。第二列中有一些 NaN 值;第一列只有数字。
我想根据第二列按升序对每个数组进行排序,将 NaN 值排除在外。这是一个大数据集,所以我宁愿不必将 NaN 值转换为零或其他东西。
我希望它像这样排序:
105. 4.
22. 10.
104. 26.
...
...
...
53. 520.
745. 902.
184. nan
19. nan
首先我尝试使用 fix_invalid
将 NaN 转换为 1x10^20
:
#data.txt has one of the arrays with 2 columns and a bunch of rows.
Data_0_30 = array(genfromtxt(fname='data.txt'))
g = open("iblah.txt", "a") #saves to file
def Sorted_i_M_W(mass):
masked = ma.fix_invalid(mass)
print >> g, array(sorted(masked, key=itemgetter(1)))
Sorted_i_M_W(Data_0_30)
g.close()
或者我用这样的东西替换了这个函数:
def Sorted_i_M_W(mass):
sortedmass = sorted( mass, key=itemgetter(1))
print >> g, array(sortedmass)
每次尝试我都会得到类似的结果:
...
[ 4.46800000e+03 1.61472200e+11]
[ 3.72700000e+03 1.74166300e+11]
[ 4.91800000e+03 1.75502300e+11]
[ 6.43500000e+03 nan]
[ 3.95520000e+04 8.38907500e+09]
[ 3.63750000e+04 1.27625700e+10]
[ 2.08810000e+04 1.28578500e+10]
...
在NaN值的位置,排序重新开始。
(对于fix_invalid
,上面摘录中的NaN 显示1.00000000e+20
值)。但我希望排序完全忽略 NaN 值。
按照我想要的方式对该数组进行排序的最简单方法是什么?
【问题讨论】:
在对列表的其余部分进行排序之前,您是否尝试过使用filter()
调用来删除带有nan
的元素?
你为什么在 python 中排序而不是使用 numpy?
在最新版本的numpy中,函数sort可以按照你所寻求的方式处理nans。这是链接docs.scipy.org/doc/numpy/reference/generated/numpy.sort.html
为什么不把 NaN 放在最后呢?我相信这最终不会那么慢得多。但是,如果可以的话,只需使用 numpy
函数会快得多。
基于@freude 的评论,您可以看到here 对浮点数进行比较的C 函数如何处理这个问题,因为np.nan != np.nan
的计算结果为True
,而任何其他涉及@987654337 的比较@返回False
。
【参考方案1】:
不确定是否可以使用numpy.sort
,但您可以肯定使用numpy.argsort
:
>>> arr
array([[ 105., 4.],
[ 53., 520.],
[ 745., 902.],
[ 19., nan],
[ 184., nan],
[ 22., 10.],
[ 104., 26.]])
>>> arr[np.argsort(arr[:,1])]
array([[ 105., 4.],
[ 22., 10.],
[ 104., 26.],
[ 53., 520.],
[ 745., 902.],
[ 19., nan],
[ 184., nan]])
【讨论】:
另一个值得注意的问题是 np.argsort 无法对包含 np.nan 的对象数组进行排序。如果数组是 dtype == object,则 np.nan 将不会正确放置(并且没有警告)【参考方案2】:如果你真的不想使用 numpy 数组,你可以对第二列进行排序,然后获取索引来调用你的数组。
只能像这样在一行中完成:
yourarray[sorted(range(len(yourarray[:,1])), key=lambda k: yourarray[:,1][k])]
【讨论】:
【参考方案3】:你可以创建一个掩码数组:
a = np.loadtxt('test.txt')
mask = np.isnan(a)
ma = np.ma.masked_array(a, mask=mask)
然后使用掩码数组对a
进行排序:
a[np.argsort(ma[:, 1])]
【讨论】:
【参考方案4】:你可以使用比较功能
def cmpnan(x, y):
if isnan(x[1]):
return 1 # x is "larger"
elif isnan(y[1]):
return -1 # x is "smaller"
else:
cmp(x[1], y[1]) # compare numbers
sorted(data, cmp=cmpnan)
见http://docs.python.org/2.7/library/functions.html#sorted
【讨论】:
【参考方案5】:如果您使用的是旧版本的 numpy 并且不想升级(或者如果您想要支持旧版本 numpy 的代码),您可以这样做:
import numpy as np
def nan_argsort(a):
temp = a.copy()
temp[np.isnan(a)] = np.inf
return temp.argsort()
sorted = a[nan_argsort(a[:, 1])]
在 numpy 的较新版本中,我认为至少 1.6,numpy 的 sort/argsort 已经具有这种行为。如果您出于某种原因需要使用 python 的排序,您可以按照其他答案中的说明制作自己的比较函数。
【讨论】:
以上是关于Python:使用 NaN 对数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章
尝试在 python 中对数组进行线性回归,但我不断收到错误“数组不得包含 infs 或 NaN”。没有 inf 或 NaN
Python\Numpy:将数组与 NAN 进行比较 [重复]