你可以使用np.fromiter
建立一個陣列與所有的值,然後切片陣列:
In [103]: it = ((x, x**2) for x in range(20))
In [104]: import itertools
In [105]: y = np.fromiter(itertools.chain.from_iterable(it), dtype=float)
In [106]: y
Out[106]:
array([ 0., 0., 1., 1., 2., 4., 3., 9., 4.,
16., 5., 25., 6., 36., 7., 49., 8., 64.,
9., 81., 10., 100., 11., 121., 12., 144., 13.,
169., 14., 196., 15., 225., 16., 256., 17., 289.,
18., 324., 19., 361.])
In [107]: y, y2 = y[::2], y[1::2]
In [108]: y
Out[108]:
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.,
11., 12., 13., 14., 15., 16., 17., 18., 19.])
In [109]: y2
Out[109]:
array([ 0., 1., 4., 9., 16., 25., 36., 49., 64.,
81., 100., 121., 144., 169., 196., 225., 256., 289.,
324., 361.])
上述設法從迭代器中的數據加載到陣列,而不使用中間的Python列表。然而,數組中的底層數據並不是連續的。許多操作上的連續陣列更快:
In [19]: a = np.arange(10**6)
In [20]: y1 = a[::2]
In [21]: z1 = np.ascontiguousarray(y1)
In [24]: %timeit y1.sum()
1000 loops, best of 3: 975 µs per loop
In [25]: %timeit z1.sum()
1000 loops, best of 3: 464 µs per loop
所以你不妨讓y
和y2
連續:
y = np.ascontiguousarray(y)
y2 = np.ascontiguousarray(y2)
調用np.ascontiguousarray
需要y
和y2
到新陣列複製非連續數據。不幸的是,我沒有看到創建y
和 y2
作爲連續數組而不復制的方法。
這裏是使用中間Python列表的比較來NumPy的切片(具有和不具有ascontiguousarray
)的基準:
import numpy as np
import itertools as IT
def using_intermediate_list(g):
lst = list(g)
y = np.fromiter((x[0] for x in lst), float, len(lst))
y2 = np.fromiter((x[1] for x in lst), float, len(lst))
return y, y2
def using_slices(g):
y = np.fromiter(IT.chain.from_iterable(g), dtype=float)
y, y2 = y[::2], y[1::2]
return y, y2
def using_slices_contiguous(g):
y = np.fromiter(IT.chain.from_iterable(g), dtype=float)
y, y2 = y[::2], y[1::2]
y = np.ascontiguousarray(y)
y2 = np.ascontiguousarray(y2)
return y, y2
def using_array(g):
y = np.array(list(g))
y, y2 = y[:, 0], y[:, 1]
return y, y2
In [27]: %timeit using_intermediate_list(((x, x**2) for x in range(10**6)))
1 loops, best of 3: 376 ms per loop
In [28]: %timeit using_slices(((x, x**2) for x in range(10**6)))
1 loops, best of 3: 220 ms per loop
In [29]: %timeit using_slices_contiguous(((x, x**2) for x in range(10**6)))
1 loops, best of 3: 237 ms per loop
In [34]: %timeit using_array(((x, x**2) for x in range(10**6)))
1 loops, best of 3: 707 ms per loop
相比'np.array([( x,x ** 2)for x in range(20)])',這個'chain'方法快1.2倍(對於更大的範圍是1.5倍)。 – hpaulj
是的,我考慮過這個。這可能不是太糟糕,因爲你將視圖返回到較大的數組中。然而,我擔心因爲參賽作品將會更加分散,因此我在閱讀數據後要做的矩陣運算效率會降低。這是我應該測試的東西。 – Erik
是的,矩陣操作在非連續陣列上會比較慢。不幸的是,我沒有看到沒有複製的情況下創建連續數組的方式。但是,上面的內容避免使用中間Python列表。 – unutbu