【问题标题】:Python: sorting an array with NaNsPython:使用 NaN 对数组进行排序
【发布时间】: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

标签: python arrays numpy nan


【解决方案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 的排序,您可以按照其他答案中的说明制作自己的比较函数。

        【讨论】:

          猜你喜欢
          • 2021-10-15
          • 1970-01-01
          • 2022-01-12
          • 1970-01-01
          • 1970-01-01
          • 2017-08-21
          • 2011-07-04
          • 2013-07-07
          • 1970-01-01
          相关资源
          最近更新 更多