棘手的Python数组排序

时间:2015-01-06 20:20:53

标签: python arrays sorting numpy

目前,我正在将一些数据加载到以下格式的内存中:

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,这个方法不会起作用吗?

感谢。

5 个答案:

答案 0 :(得分:4)

这可以在没有显式循环的情况下完成。我将使用较小的数据集,并创建一个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]])

答案 1 :(得分: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.]])

答案 2 :(得分:1)

由于您的矩阵非常小(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)

答案 3 :(得分:1)

你的循环无效,因为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 :(得分:-1)

试试这个:

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

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