创建2D numpy数组的Pythonic方式

1 投票
2 回答
722 浏览
提问于 2025-04-16 14:11

我有一个函数 gen(),它返回一个包含 nElements 个浮点数的 numpy 数组。我想找一种更符合 Python 风格的(最好是一行代码)方法来做以下事情:

a = zeros((nSamples, nElements))
for i in xrange(nSamples):
     a[i,:] = gen()

这是一种实现方式:

a = array([gen() for i in xrange(nSamples)]).reshape((nSamples, nElements))

不过,这种方法速度稍慢,因为没有提前分配好 numpy 数组:

import time
from numpy import *

nSamples  = 100000
nElements = 100

start = time.time()
a = array([gen() for i in xrange(nSamples)]).reshape((nSamples, nElements))
print (time.time() - start)

start = time.time()
a = zeros((numSamples, nElements))
for i in xrange(numSamples):
    a[i,:] = gen()
print (time.time() - start)

输出:

1.82166719437
0.502261161804

那么,有没有办法在保持预先分配数组的情况下,实现同样的一行代码呢?

谢谢,
-Nate

2 个回答

9

这可能没有直接回答你的问题,但因为你在标题中提到了Pythonic,所以我想说一下。请理解,Pythonic并不一定意味着用“一行代码”或者最聪明、最简短的方式来做事情。恰恰相反,Pythonic的代码更注重清晰易懂。

就你的代码而言,我觉得:

a = zeros((nSamples, nElements))
for i in xrange(nSamples):
     a[i,:] = gen()

比下面这个:

a = array([gen() for i in xrange(nSamples)]).reshape((nSamples, nElements))

要清晰得多。因此,我不会说第二个更符合Pythonic的风格,可能反而不太符合。

0

我觉得这个可以满足你的需求:

a = vstack([ gen() for _ in xrange(nSamples) ])

因为我无法访问你的 gen 函数,所以无法进行时间测试。另外,这个方法(还有你的一行代码)在内存使用上没有你那个 for 循环版本那么友好。你的一行代码会把所有 gen() 的输出都存起来,然后再构建数组,而 for 循环只需要同时在内存中保留一个 gen() 的输出(还有那个 numpy 数组)。

撰写回答