Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从numpy矩阵中快速提取子矩阵的方法_Python_Python 3.x_Numpy_Submatrix - Fatal编程技术网

Python 从numpy矩阵中快速提取子矩阵的方法

Python 从numpy矩阵中快速提取子矩阵的方法,python,python-3.x,numpy,submatrix,Python,Python 3.x,Numpy,Submatrix,我有一个巨大的.csv文件(~2GB),我用read\u csv导入我的程序,然后用as\u matrix转换成一个numpy矩阵。生成的矩阵的形式类似于下面给定示例中的data\u mat。我现在的问题是,我需要提取具有相同uuid4(矩阵第一列中的条目)的块。子矩阵然后由另一个函数处理。我下面的例子似乎不是最好的方法。更快的方法是受欢迎的 import numpy as np data_mat = np.array([['f9f1dc71-9457-4d17-b5d1-e63b5a766f8

我有一个巨大的
.csv
文件(~2GB),我用
read\u csv
导入我的程序,然后用
as\u matrix
转换成一个numpy矩阵。生成的矩阵的形式类似于下面给定示例中的
data\u mat
。我现在的问题是,我需要提取具有相同uuid4(矩阵第一列中的条目)的块。子矩阵然后由另一个函数处理。我下面的例子似乎不是最好的方法。更快的方法是受欢迎的

import numpy as np
data_mat = np.array([['f9f1dc71-9457-4d17-b5d1-e63b5a766f84', 4, 3, 1],\
                     ['f9f1dc71-9457-4d17-b5d1-e63b5a766f84', 3, 1, 1],\
                     ['f9f1dc71-9457-4d17-b5d1-e63b5a766f84', 3, 3, 1],\
                     ['f9f1dc71-9457-4d17-b5d1-e63b5a766f84', 6, 1, 1],\
                     ['f35fb25b-dddc-458a-9f71-0a9c2c202719', 3, 4, 1],\
                     ['f35fb25b-dddc-458a-9f71-0a9c2c202719', 3, 1, 1],\
                     ['a4cf92fc-0624-4a00-97f6-0d21547e3183', 3, 2, 1],\
                     ['a4cf92fc-0624-4a00-97f6-0d21547e3183', 3, 9, 0],\
                     ['a4cf92fc-0624-4a00-97f6-0d21547e3183', 3, 1, 0],\
                     ['a4cf92fc-0624-4a00-97f6-0d21547e3183', 5, 1, 1],\
                     ['a4cf92fc-0624-4a00-97f6-0d21547e3183', 3, 1, 1],\
                     ['d3a8a9d0-4380-42e3-b35f-733a9f9770da', 3, 6, 10]],dtype=object)

unique_ids, indices = np.unique(data_mat[:,0],return_index=True,axis=None)
length = len(data_mat)
i=0
for idd in unique_ids:
    index = indices[i]
    k=0
    while ((index+k)<length and idd == data_mat[index+k,0]):        
        k+=1
    tmp_mat=data_mat[index:(index+k),:]
    # do something with tmp_mat ...
    print(tmp_mat)
    i+=1
将numpy导入为np
数据材料=np.数组(['f9f1dc71-9457-4d17-b5d1-e63b5a766f84',4,3,1]\
[f9f1dc71-9457-4d17-b5d1-e63b5a766f84',3,1,1]\
[f9f1dc71-9457-4d17-b5d1-e63b5a766f84',3,3,1]\
[f9f1dc71-9457-4d17-b5d1-e63b5a766f84',6,1,1]\
[f35fb25b-dddc-458a-9f71-0a9c2c202719',3,4,1]\
[f35fb25b-dddc-458a-9f71-0a9c2c202719',3,1,1]\
[a4cf92fc-0624-4a00-97f6-0d21547e3183',3,2,1]\
[a4cf92fc-0624-4a00-97f6-0d21547e3183',3,9,0]\
[a4cf92fc-0624-4a00-97f6-0d21547e3183',3,1,0]\
[a4cf92fc-0624-4a00-97f6-0d21547e3183',5,1,1]\
[a4cf92fc-0624-4a00-97f6-0d21547e3183',3,1,1]\
[d3a8a9d0-4380-42e3-b35f-733a9f9770da',3,6,10]],数据类型=对象)
唯一ID,索引=np.unique(数据表[:,0],返回索引=True,轴=None)
长度=长度(数据线)
i=0
对于唯一\u ID中的idd:
指数=指数[i]
k=0

而((索引+k)优化的想法是,一旦我们进入循环,就可以最小化计算。因此,考虑到这一点,我们将重新排列数组的行,按第一列排序。然后,获取定义边界的索引。最后,启动循环,只需在每次迭代中为每个组切片,就可以得到一个子矩阵。切片实际上是在使用阵列时是免费的,因此这应该对我们有所帮助

因此,一种实施方式是-

a0 = data_mat[:,0]
sidx = a0.argsort()
sd = data_mat[sidx] # sorted data_mat
idx = np.flatnonzero(np.concatenate(( [True], sd[1:,0] != sd[:-1,0], [True] )))
for i,j in zip(idx[:-1], idx[1:]):
    tmp_mat = sd[i:j]
    print tmp_mat
如果希望将每个子矩阵存储为一个数组,并将数组列表作为最终输出,只需执行以下操作-

[sd[i:j] for i,j in zip(idx[:-1], idx[1:])]

用于排序的
数据\u mat

对于已按示例中所示排序的
data\u mat
,我们可以避免对整个数组进行排序,直接使用第一列,如下所示-

a0 = data_mat[:,0]
idx = np.flatnonzero(np.concatenate(( [True], a0[1:] != a0[:-1], [True] )))

for i,j in zip(idx[:-1], idx[1:]):
    tmp_mat = data_mat[i:j]
    print(tmp_mat)
同样,要将所有这些子矩阵作为数组列表,请使用-

[data_mat[i:j] for i,j in zip(idx[:-1], idx[1:])]
请注意,我们将使用此方法得到的子矩阵的顺序与前面方法中的排序顺序不同


分类数据的基准测试 接近-

# @Daniel F's soln-2
def split_app(data_mat):
    idx = np.flatnonzero(data_mat[1:, 0] != data_mat[:-1, 0]) + 1
    return np.split(data_mat, idx)

# Proposed in this post
def zip_app(data_mat):
    a0 = data_mat[:,0]
    idx = np.flatnonzero(np.concatenate(( [True], a0[1:] != a0[:-1], [True] )))
    return [data_mat[i:j] for i,j in zip(idx[:-1], idx[1:])]
时间安排-

在这个示例中,我们有一个最大长度
6
的子矩阵。因此,让我们扩展到一个更大的情况,使其保持相同的模式-

In [442]: a = np.random.randint(0,100000,(6*100000,4)); a[:,0].sort()

In [443]: %timeit split_app(a)
10 loops, best of 3: 88.8 ms per loop

In [444]: %timeit zip_app(a)
10 loops, best of 3: 40.2 ms per loop

In [445]: a = np.random.randint(0,1000000,(6*1000000,4)); a[:,0].sort()

In [446]: %timeit split_app(a)
1 loop, best of 3: 917 ms per loop

In [447]: %timeit zip_app(a)
1 loop, best of 3: 414 ms per loop

您可以使用布尔索引来实现这一点

unique_ids = np.unique(data_mat[:, 0])
masks = np.equal.outer(unique_ids, data_mat[:, 0])
for mask in masks:
    tmp_mat = data_mat[mask]
    # do something with tmp_mat ...
    print(tmp_mat)

如果唯一ID已经分组,您可以使用
np.split
,类似于@Divakar

idx = np.flatnonzero(data_mat[1:, 0] != data_mat[:-1, 0]) + 1
for tmp_mat in np.split(data_mat, idx):
    # do something with tmp_mat ...
    print(tmp_mat)

最好的方法可能是在pandas中进行,这是针对这一点进行了高度优化的。这是您想要的。也可以在此处查看有关numpy缺失功能的一些讨论(可能是对pandas的赞扬)。唯一ID是否总是这样分组(即按
数据\u mat[:,0]
或其他方式排序)?是的,唯一的ID总是这样组合在一起。我应该提到这一点。为什么您可能希望避免性能方面的
np.split
。我的计时显示这与您的一样快,@Divakar。没有连接可能会有帮助。不要比较我的ID和您的ID:)只是概括说明为什么您可能希望避免
split
。但是在比较中,我想我们需要一个比样本更大的数据集。如果你对时间感兴趣,请在我的帖子中添加基准测试。您将需要更少的分组数量,以帮助避免串联+拆分方法更好地工作。