棘手的 Python 数组排序

Tricky Python array sorting

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

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] 很简单,但问题是列表没有排序,第二列和第三列中的条目是浮点数,所以我不能在切片。

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

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 运行,此方法是否有效?

谢谢。

如果我理解你的问题,那么我猜你想根据索引对数组进行排序。为此,您可以使用 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.]])

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

试试这个:

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

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

你的循环没有工作,因为你的 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 提供的第二个示例是执行此操作的更简洁的方法,也是更强大的解决方案。

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