Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.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 取决于np.nditer变量的迭代器数_Python_Arrays_Numpy - Fatal编程技术网

Python 取决于np.nditer变量的迭代器数

Python 取决于np.nditer变量的迭代器数,python,arrays,numpy,Python,Arrays,Numpy,我必须迭代numpy数组,这些数组的数目在程序的每次迭代中都是不同的。目标是计算这些数组中相同元素之间的方差。以下是我编写的代码: for a,s,m in np.nditer([cost_surfaceS[i].ravel() for i in range(0,len(cost_surfaceS),1)]): arr = [a, s, m] if(float(arr[0]) != float("-inf")): variance = np.var(arr,dtype

我必须迭代numpy数组,这些数组的数目在程序的每次迭代中都是不同的。目标是计算这些数组中相同元素之间的方差。以下是我编写的代码:

for a,s,m  in np.nditer([cost_surfaceS[i].ravel() for i in range(0,len(cost_surfaceS),1)]):
arr = [a, s, m]
    if(float(arr[0]) != float("-inf")):
        variance = np.var(arr,dtype = np.float32)
        variances.append(variance)
    else:
        variances.append(float("-inf"))

其中cost_surfaceS是一个包含所有我的numpy数组的列表。问题是,这段代码适用于创建的3个numpy数组,我想更改“a,s,m”,以获得取决于创建的numpy数组数量的迭代器数量(即
len(cost_surfaceS)
)。这是一种方法吗?

我同意@Bickknght的观点,即不需要拆包。处理未知或数量可变的元素时,不要使用
解包

In [57]: alist = [np.arange(10), np.arange(10,20), np.arange(20,30)]                                            
制作一个数组列表,其中我们不需要
ravel

In [58]: for arr  in np.nditer(alist): 
    ...:     print(arr) 
    ...:                                                                                                        
(array(0), array(10), array(20))
(array(1), array(11), array(21))
(array(2), array(12), array(22))
(array(3), array(13), array(23))
(array(4), array(14), array(24))
(array(5), array(15), array(25))
(array(6), array(16), array(26))
(array(7), array(17), array(27))
(array(8), array(18), array(28))
(array(9), array(19), array(29))
将此与直接列表zip迭代进行比较:

In [59]: for arr in zip(*alist): 
    ...:     print(arr) 
    ...:                                                                                                        
(0, 10, 20)
(1, 11, 21)
(2, 12, 22)
(3, 13, 23)
(4, 14, 24)
(5, 15, 25)
(6, 16, 26)
(7, 17, 27)
(8, 18, 28)
(9, 19, 29)
不同之处在于,
nditer
生成0d数组而不是标量。因此元素有一个形状(
(0,)
)和
dtype
。或者在某些情况下,您希望修改数组(但必须将它们定义为
read/write
),否则
nditer
不会提供任何真正的优势

In [62]: %%timeit 
    ...: ll = [] 
    ...: for arr  in np.nditer(alist): 
    ...:     ll.append(np.var(arr)) 
    ...:                                                                                                        
539 µs ± 17.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [63]: %%timeit 
    ...: ll = [] 
    ...: for arr  in zip(*alist): 
    ...:     ll.append(np.var(arr)) 
    ...:                                                                                                        
524 µs ± 3.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
如果可以避免Python级别的循环,那么速度会快得多:

In [65]: np.stack(alist,1)                                                                                      
Out[65]: 
array([[ 0, 10, 20],
       [ 1, 11, 21],
       [ 2, 12, 22],
       [ 3, 13, 23],
       [ 4, 14, 24],
       [ 5, 15, 25],
       [ 6, 16, 26],
       [ 7, 17, 27],
       [ 8, 18, 28],
       [ 9, 19, 29]])
In [66]: np.var(np.stack(alist,1),axis=1)                                                                       
Out[66]: 
array([66.66666667, 66.66666667, 66.66666667, 66.66666667, 66.66666667,
       66.66666667, 66.66666667, 66.66666667, 66.66666667, 66.66666667])
In [67]: timeit np.var(np.stack(alist,1),axis=1)                                                                
66.7 µs ± 1.47 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
我没有尝试测试
-inf

===

nditer
的另一个重要区别是,它以一种简单的方式在所有元素上迭代—实际上,它是执行ravel:

列出二维阵列

In [81]: alist = [np.arange(10.).reshape(2,5), np.arange(10,20.).reshape(2,5), np.arange(20,30.).reshape(2,5)]  
普通迭代在第一个维度上运行-在本例中为2,因此压缩的元素是数组:

In [82]: for arr in zip(*alist): 
    ...:     print(arr) 
    ...:                                                                                                        
(array([0., 1., 2., 3., 4.]), array([10., 11., 12., 13., 14.]), array([20., 21., 22., 23., 24.]))
(array([5., 6., 7., 8., 9.]), array([15., 16., 17., 18., 19.]), array([25., 26., 27., 28., 29.]))
nditer
生成的元组与1d数组中的元组相同。有些情况下可以,但如果不需要,则很难避免

In [83]: for arr  in np.nditer(alist): 
    ...:     print(arr) 
    ...:                                                                                                        
(array(0.), array(10.), array(20.))
(array(1.), array(11.), array(21.))
(array(2.), array(12.), array(22.))
(array(3.), array(13.), array(23.))
(array(4.), array(14.), array(24.))
(array(5.), array(15.), array(25.))
(array(6.), array(16.), array(26.))
(array(7.), array(17.), array(27.))
(array(8.), array(18.), array(28.))
(array(9.), array(19.), array(29.))
正如@hpaulj所解释的,这是一个解决方案。使用2d数组而不是1d只需要使用两次此函数,如下代码所示:

variances = []
for arr in zip(*cost_surfaceS):
    for element in zip(*arr):
        if(float("-inf") not in element):
            variance = np.var(element, dtype=np.float32)
            variances.append(variance)
        else:
            variances.append(float("-inf"))

-inf
值由if条件处理,以避免计算至少包含一个无穷大值的数组的方差。

只需将
用于np.nditer(…)
(并去掉下一行)?感谢您的回答,这确实非常容易(而且可能)不幸的是,我将无法在接下来的10天内对其进行测试,但对于“-inf”,我将尝试使用堆栈函数,因为这是最快的,如果它不起作用,则使用简单的“if”我想zip函数的条件应该有效。您可能想问一个新问题,重点是如何以“矢量化”的方式处理
-inf
值。遇到
inf
时的默认行为是发出警告,然后返回
np.nan
。我现在还没有清醒到能够解决这个问题。