在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)
我发现我必须先创建一个列表,然后再用“array”把它转换成数组。有没有什么办法可以避免这些步骤?这些转换的代码让我的代码看起来很乱……我该如何从一开始就直接创建“my_array”,让它就是一个数组呢?
4 个回答
19
推荐的做法是在循环之前先分配好内存,然后通过切片和索引来插入数据。
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)
虽然numpy提供了一个array.resize()
的方法,但在循环中使用这个方法会很慢,因为每次都要重新分配内存。如果你真的需要灵活性,那就只能从一个list
创建一个array
了。
补充一下:如果你担心为数据分配了太多内存,可以使用上面的方法先多分配一些,然后在循环结束后,用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
一般原则是“分配比你认为需要的更多的内存,如果情况变化,尽量少调整数组的大小”。虽然把大小翻倍可能看起来有点过,但实际上这是许多其他语言的标准库中几种数据结构使用的方法(例如,java.util.Vector
默认就是这样做的。我觉得C++中的几个std::vector
的实现也是这样)。
36
NumPy 提供了一个叫 'fromiter' 的方法:
def myfunc(n):
for i in range(n):
yield i**2
np.fromiter(myfunc(5), dtype=int)
这个方法会生成
array([ 0, 1, 4, 9, 16])
-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))