gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-28 22:24:54 24 4
gpt4 key购买 nike

我有一个巨大的.csv我用 read_csv 在我的程序中导入的文件 (~2GB)然后用 as_matrix 转换成一个 numpy 矩阵.生成的矩阵的形式类似于 data_mat在下面给出的示例中。我现在的问题是,我需要提取具有相同 uuid4 的 block (矩阵第一列中的条目)。然后由另一个函数处理子矩阵。看来我下面的例子并不是最好的方法。欢迎使用更快的方法。

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

最佳答案

优化这个想法就是在我们进入循环后最小化计算。因此,考虑到这一点,我们将重新排列数组的行,按第一列排序。然后,获取定义边界的索引。最后,开始我们的循环并简单地对每个组进行切片以在每次迭代时得到一个子矩阵。在处理数组时,切片实际上是免费的,因此这应该对我们有所帮助。

因此,一种实现方式是 -

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:])]

用于排序的data_mat

对于 data_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:])]

请注意,我们将使用此方法获得的子矩阵的顺序与之前方法中完成的排序不同。


排序data_mat的基准测试

方法-

# @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

关于python - 从numpy矩阵中提取子矩阵的快速方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46023698/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com