在Python中通过迭代在numpy/scipy中构建一个数组?

22 python numpy scipy

通常,我通过迭代一些数据来构建数组,例如:

my_array = []
for n in range(1000):
  # do operation, get value 
  my_array.append(value)
# cast to array
my_array = array(my_array)
Run Code Online (Sandbox Code Playgroud)

我发现我必须首先构建一个列表,然后将它(使用"array")转换为数组.这有什么方法吗?所有这些转换调用使代码混乱......我怎样才能迭代地构建"my_array",从一开始它就是一个数组?

Ste*_*alt 32

NumPy提供了'fromiter'方法:

def myfunc(n):
    for i in range(n):
        yield i**2


np.fromiter(myfunc(5), dtype=int)
Run Code Online (Sandbox Code Playgroud)

产量

array([ 0,  1,  4,  9, 16])
Run Code Online (Sandbox Code Playgroud)

  • 使用`np.fromiter`并且事先知道数组的大小时,可以将其作为参数传递,以便预先分配数组.这极大地提高了性能.所以在上面的例子中,执行:`np.fromiter(myfunc(5),dtype = int,count = 5)` (2认同)

Chi*_*chi 15

建议的方法是在循环之前预分配并使用切片和索引进行插入

my_array = numpy.zeros(1,1000)
for i in xrange(1000):
    #for 1D array
    my_array[i] = functionToGetValue(i)
    #OR to fill an entire row
    my_array[i:] = functionToGetValue(i)
    #or to fill an entire column
    my_array[:,i] = functionToGetValue(i)
Run Code Online (Sandbox Code Playgroud)

numpy的确实提供了一个array.resize()方法,但是这将是慢得多由于在循环中重新分配存储器的成本.如果你必须有灵活性,那么恐怕唯一的办法就是创造一个array来自list.

编辑:如果你担心你为你的数据分配了太多的内存,我会使用上面的方法进行过度分配,然后在完成循环时,使用掉掉数组中未使用的位array.resize().这将是迄今为止,快于不断重新分配循环内的数组.

编辑:响应@ user248237的评论,假设你知道数组的任何一个维度(为简单起见):

my_array = numpy.array(10000, SOMECONSTANT)

for i in xrange(someVariable):
    if i >= my_array.shape[0]:
        my_array.resize((my_array.shape[0]*2, SOMECONSTANT))

    my_array[i:] = someFunction()

#lop off extra bits with resize() here
Run Code Online (Sandbox Code Playgroud)

一般原则是"分配比您认为需要的更多,如果事情发生变化,尽可能少地调整阵列大小".倍增尺寸可以被认为是过度的,但实际上这是用不同的语言几个标准库使用的几个数据结构的方法(java.util.Vector通过默认例如执行此操作.我想的几种实现std::vector在C++中做到这一点以及).

  • 如果我不提前知道尺寸怎么办? (3认同)

dou*_*oug -2

如果我正确理解你的问题,这应该做你想要的:

# the array passed into your function
ax = NP.random.randint(10, 99, 20).reshape(5, 4)

# just define a function to operate on some data
fnx = lambda x : NP.sum(x)**2

# apply the function directly to the numpy array
new_row = NP.apply_along_axis(func1d=fnx, axis=0, arr=ax)

# 'append' the new values to the original array
new_row = new_row.reshape(1,4)
ax = NP.vstack((ax, new_row))
Run Code Online (Sandbox Code Playgroud)

  • 由于这是公认的答案,我不得不这样说:我见过 vstack 经常这样使用。人们应该意识到这确实(!)性能不佳。如果您确实以这种方式构建了一个大数组,您会执行大量不必要的内存复制操作。请参阅下面的答案 (6认同)