Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Numpy同时使用fromiter创建两个阵列_Python_Arrays_Numpy - Fatal编程技术网

Python Numpy同时使用fromiter创建两个阵列

Python Numpy同时使用fromiter创建两个阵列,python,arrays,numpy,Python,Arrays,Numpy,我有一个迭代器,看起来像下面这样 it = ((x, x**2) for x in range(20)) 我想要的是两个数组。一个是xs,另一个是x**2s,但我实际上不知道元素的数量,并且我无法从一个条目转换到另一个条目,因此我无法构建第一个条目,然后从第一个条目构建第二个条目 如果我只有一个未知大小的结果,我可以使用np.fromiter让它动态有效地分配,例如 y = np.fromiter((x[0] for x in it), float) 有了两个,我希望我能像 ita, itb

我有一个迭代器,看起来像下面这样

it = ((x, x**2) for x in range(20))
我想要的是两个数组。一个是
x
s,另一个是
x**2
s,但我实际上不知道元素的数量,并且我无法从一个条目转换到另一个条目,因此我无法构建第一个条目,然后从第一个条目构建第二个条目

如果我只有一个未知大小的结果,我可以使用
np.fromiter
让它动态有效地分配,例如

y = np.fromiter((x[0] for x in it), float)
有了两个,我希望我能像

ita, itb = itertools.tee(it)
y = np.fromiter((x[0] for x in ita), float)
y2 = np.fromiter((x[1] for x in itb), float)
但是因为第一个调用耗尽了迭代器,我最好还是这样做

lst = list(it)
y = np.fromiter((x[0] for x in lst), float, len(lst))
y2 = np.fromiter((x[1] for x in lst), float, len(lst))

因为不管怎么说,tee都会填写一份与整个列表大小相同的表格。在将迭代器再次复制到数组之前,我希望避免将迭代器复制到列表中,但我想不出一种不完全手动地增量构建数组的方法。此外,
fromiter
似乎是用c编写的,因此用python编写它可能与首先制作一个列表没有不可忽略的区别。

您可以使用
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
):



np.array([(x,x**2)表示范围内的x(20)])
相比,这种
方法快1.2倍(1.5倍表示范围更大)。是的,我考虑过这一点。这可能并不太糟糕,因为您正在将视图返回到更大的数组中。然而,我担心的是,由于条目在ram中的间隔会更大,所以我在读取数据后要执行的矩阵操作的效率会更低。这可能是我应该测试的。是的,在非连续数组上矩阵运算会慢一些。不幸的是,我看不到一种在不复制的情况下创建连续数组的方法。但是,上面确实避免了使用中间Python列表。
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