注意:我正在使用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值。
按照我想要的方式对这个数组进行排序的最简单方法是什么?
答案 0 :(得分:5)
不确定是否可以使用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]])
答案 1 :(得分:4)
您可以创建一个蒙版数组:
a = np.loadtxt('test.txt')
mask = np.isnan(a)
ma = np.ma.masked_array(a, mask=mask)
然后使用蒙面数组对a
进行排序:
a[np.argsort(ma[:, 1])]
答案 2 :(得分:1)
您可以使用比较功能
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)
答案 3 :(得分:1)
如果您使用的是较旧版本的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的排序,可以按照其他答案中的描述制作自己的比较函数。
答案 4 :(得分:0)
如果你真的不想使用numpy数组,你可以对第二列进行排序,然后获取索引来调用你的数组。
它可以像这样在一行中完成:
yourarray[sorted(range(len(yourarray[:,1])), key=lambda k: yourarray[:,1][k])]