逐步构建numpy数组的最佳方法是什么?

10

如何以最高效的方式逐步构建一个numpy数组,例如每次添加一行,而不事先知道最终大小?我的用例如下。我需要加载一个大文件(10-100M行),其中每行都需要字符串处理,并应形成numpy数组的一行。

是将数据加载到临时Python列表中并转换为数组更好,还是numpy中存在某些现有机制可以使其更有效率?


еҗ‘зҺ°жңүзҡ„ndarrayж·»еҠ иЎҢеҸҜдҪҝз”Ёnumpy.concatenateжҲ–numpy.vstackе®ҢжҲҗгҖӮеҚ•дёӘиЎҢзңӢиө·жқҘдјҡжҳҜд»Җд№Ҳж ·еӯҗпјҹ - derricw
2
loadtxtgenfromtxt都会逐行收集一个列表的列表,并在最后将其转换为数组。它们的代码是用Python编写的,所以你可以浏览它。 - hpaulj
1
如果数据格式已知,每行都是数据,您可以计算行数并预分配数组。这可能不会更快,但您可以避免创建两个保存相同大量数据的对象。请参阅https://dev59.com/X3RA5IYBdhLWcg3wvQlh。 - Alan
内存在这里不应该是一个问题,尽管它可能是某些情况下的可行解决方案。 - Andrzej Pronobis
@derricw 不行!vstack等函数会清空并重新分配所有的内存!这将耗费很长时间。如果可能的话,请不要使用它们! - Gulzar
@Gulzar 嘿,是的,请看下面我的回答。 - derricw
2个回答

10

你应该将每一行添加到一个列表中,然后在之后将其转换为ndarray,这样可以获得更好的性能表现。

下面是一个测试,我将ndarray添加到列表中10000次,然后在完成后生成一个新的ndarray:

row = np.random.randint(0,100, size=(1,100))

我使用IPython笔记本计时:

%%timeit
l = [row]

for i in range(10000):
    l.append(row)

n = np.array(l)

-> 10次循环,3次测试中最佳结果:每个循环132毫秒

以下是一个测试,在该测试中我连接了每一行:

%%timeit
l = row

for i in range(10000):
    l = np.concatenate((l, row),axis=0)

-> 1个循环,3次中最佳: 每个循环23.1秒

慢得多。

第一种方法唯一的问题是你会同时在内存中拥有列表和数组,因此可能会出现RAM问题。您可以通过分块来避免这种情况。


即使我们在向列表追加每一行时都复制一份,这确实会产生很大的差异。 - Andrzej Pronobis

3
在我的笔记本电脑上,使用1个核心的英特尔i5处理器,主频为1.7 GHz:
%%timeit
l = [row]

for i in range(10000):
    l.append(row)

n = np.array(l)
100 loops, best of 3: 5.54 ms per loop

我尝试使用纯numpy(也许有人知道更好的解决方案)

%%timeit
l = np.empty( (1e5,row.shape[1]) )
for i in range(10000):
    l[i] = row
l = l[np.all(l > 1e-100, axis=1)]

10 loops, best of 3: 18.5 ms per loop

有趣的是,使用np.empty进行预分配仍然不比使用列表更快。 - derricw
如果我预先分配适当大小的数组,速度是相似的。但由于 OP 不知道大小,所以我必须使用一个更大的数组。 - Moritz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接