【问题标题】:Tricky Python array sorting棘手的 Python 数组排序
【发布时间】:2015-03-04 14:05:51
【问题描述】:

目前,我正在将一些数据加载到表单的内存中:

5.579158e-19    0   0
5.678307e-19    1   0
...
6.041513e-19    27  0
5.938317e-19    28  0
...
5.978803e-19    38  1
5.590008e-19    39  1 
5.588807e-19    0   2
5.670948e-19    1   2
...

以此类推:

import numpy as np
data_res = np.genfromtxt('/path/data.csv',delimiter=';', dtype = float)

我想要的是一个 40x40 矩阵 mat,其中索引是第二列和第三列中的条目。第一个条目 mat[0,0] = data[0,0] 很简单,但问题是列表没有排序,第二列和第三列中的条目是浮点数,所以我不能在切片。

我尝试了双循环方法,但它不能正常工作。

mat = np.zeros((40,40))

for k in range(0,40):
    for j in range(0,40):
        mat[k,j] = data_res[k*j,0]

如果索引的范围是 1-40 而不是 0-39,这种方法是否有效?

谢谢。

【问题讨论】:

    标签: python arrays sorting numpy


    【解决方案1】:

    这可以在没有显式循环的情况下完成。我将使用一个较小的数据集,并创建一个 10x10 数组mat。如果索引 (i,j) 不在 CSV 文件中,mat[i,j] 将为 0。

    这是输入文件:

    In [27]: !cat data.csv
    0.1    0   0
    0.2    1   0
    0.3    7   0
    0.4    8   0
    0.5    8   1
    0.6    9   1 
    0.7    0   2
    0.8    1   2
    0.9    9   9
    

    使用genfromtxt 将数据读入具有三个字段valuesij 的结构化数组。

    In [28]: data = np.genfromtxt('data.csv', dtype=None, names=['values', 'i', 'j'])
    

    通过使用dtype=None,我们告诉genfromtxt 根据文件中找到的内容确定数据类型。在这种情况下,'values' 字段将是浮点数,'i''j' 字段将是整数。

    创建数组mat:

    In [29]: mat = np.zeros((10, 10))
    

    将数据分配给mat

    In [30]: mat[data['i'], data['j']] = data['values']
    
    In [31]: mat
    Out[31]: 
    array([[ 0.1,  0. ,  0.7,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
           [ 0.2,  0. ,  0.8,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
           [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
           [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
           [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
           [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
           [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
           [ 0.3,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
           [ 0.4,  0.5,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
           [ 0. ,  0.6,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0.9]])
    

    【讨论】:

      【解决方案2】:

      如果我理解您的问题,那么我猜您想根据索引对数组进行排序。为此,您可以使用numpy.lexsort:

      >>> arr = np.arange(16).reshape(4, 4).astype(float)
      >>> x, y = arr.shape
      >>> indices = np.vstack(np.unravel_index(np.arange(x*y), (y, x))).T
      >>> np.random.shuffle(indices)
      >>> arr = np.hstack((arr.flatten()[:, None], indices))
      >>> arr  # now this looks like your dataset, first column is data and other two are indices
      array([[  0.,   1.,   3.],
             [  1.,   1.,   2.],
             [  2.,   3.,   0.],
             [  3.,   0.,   1.],
             [  4.,   0.,   0.],
             [  5.,   2.,   0.],
             [  6.,   0.,   2.],
             [  7.,   2.,   3.],
             [  8.,   3.,   2.],
             [  9.,   0.,   3.],
             [ 10.,   3.,   1.],
             [ 11.,   1.,   0.],
             [ 12.,   3.,   3.],
             [ 13.,   1.,   1.],
             [ 14.,   2.,   2.],
             [ 15.,   2.,   1.]])
      >>> arr[np.lexsort((arr[:, 2], arr[:,1]))][:,0].reshape(4, 4)
      array([[  4.,   3.,   6.,   9.],
             [ 11.,  13.,   1.,   0.],
             [  5.,  15.,  14.,   7.],
             [  2.,  10.,   8.,  12.]])
      

      【讨论】:

        【解决方案3】:

        您的循环无法正常工作,因为您的 data_res[k*j,0] 没有按照我认为的那样做。

        要获得所需的结果,请尝试data_res[(k*40)+j,0]

        dim = 40
        mat = np.zeros((dim,dim))
        
        for k in range(0,dim):
            for j in range(0,dim):
                mat[k,j] = data_res[(k*dim)+j,0]
        

        这是基于您的索引实际上已经排序的假设。正如ajcr 指出的那样,如果不是,您将需要一种不同的方法。

        更新: hooked 提供的第二个示例是一种更简洁的方法,也是一种更强大的解决方案。

        【讨论】:

          【解决方案4】:

          由于您的矩阵非常小 (40x40),因此用于读取文件并输入 numpy 数组的纯 Python 解决方案可能更适合您:

          raw = '''5.579158e-19    0   0
          5.678307e-19    1   0
          6.041513e-19    27  0
          5.588807e-19    0   2
          5.670948e-19    1   2'''
          
          import numpy as np
          mat = np.zeros((40,40))
          
          for line in raw.split('\n'):
              z,i,j = line.split()
              mat[int(i),int(j)]=float(z)
          
          print mat
          

          上面的示例使用字符串来保存文件示例的数据。如果文件名为data.txt,您将改为运行:

          with open("data.txt") as FIN:
              for line in FIN:
                  z,i,j = line.split()
                  mat[int(i),int(j)]=float(z)
          

          【讨论】:

            【解决方案5】:

            试试这个:

            mat = np.zeros((40,40))
            
            for i in range(0,len(data_res)):
                mat[data_res[1] , data_res[2]] = data_res[0]
            

            【讨论】:

              猜你喜欢
              • 2018-03-14
              • 1970-01-01
              • 2011-08-16
              • 1970-01-01
              • 2023-03-29
              • 2012-08-21
              • 1970-01-01
              • 2010-11-18
              • 1970-01-01
              相关资源
              最近更新 更多