我想做些简单的事情,但还没有找到一种明智的方法。
假设我有一个numpy
数组,其中包含3行,如下所示:
import numpy as np
a = np.array([[0.514, 0.966, 0.443, 0.95 , 0.524, 0.423, 0.75 , 0.463, 0.721, 0.089],
[0.929, 0.014, 0.275, 0.521, 0.739, 0.612, 0.366, 0.469, 0.575, 0.533],
[0.235, 0.084, 0.994, 0.713, 0.421, 0.851, 0.66 , 0.231, 0.699, 0.216]])
我想在每对行上应用以下函数 并累积结果 即(row0与row1)->(输出第3行的上一步),依此类推 :
def myfunc(x,y):
return x**2 + y**2 - x*y
手动显示如下:
tmp1 = myfunc(a[0],a[1])
results = myfunc(tmp1,a[2])
现在,我想以一种聪明的方式将其概括为一般N (N = a.shape[0])
。
我已经尝试过基于列表理解的方法,但是无法将其推广到任何N。
编辑1:
N = 4的示例:
tmp1 = myfunc(a[0],a[1])
tmp2 = myfunc(tmp1,a[2])
results = myfunc(tmp2,a[3])
答案 0 :(得分:1)
这是在第一个维度(即axis-0)上使用for
循环解决此问题的一种简单方法:
# your custom function; slightly rewritten because
# * based multiplication is faster than `pow()`
In [93]: def myfunc(x,y):
...: return x*x + y*y - x*y
# to be replenished after each iteration
In [95]: res = a[0]
# go over rows and compute the results using `myfunc()`
In [96]: for i in range(a.shape[0]-1):
...: curr_step_res = myfunc(res, a[i+1])
...: res = curr_step_res[:]
# final result
In [97]: res
Out[97]:
array([0.32468859, 0.775874 , 0.861402 , 0.4852772 , 0.18264236,
0.56028635, 0.33515591, 0.05036018, 0.37391415, 0.05364418])
In [99]: tmp1 = myfunc(a[0],a[1])
In [100]: results = myfunc(tmp1,a[2])
In [101]: np.allclose(results, res)
Out[101]: True
# sample array to work with
In [102]: a = np.random.random_sample((4, 6))
# to be replenished after each iteration
In [103]: res = a[0]
In [104]: for i in range(a.shape[0]-1):
...: curr_step_res = myfunc(res, a[i+1])
...: res = curr_step_res[:]
In [105]: res
Out[105]:
array([0.51971283, 0.61377465, 0.0838452 , 0.2201938 , 0.54028219,
0.19318569])
# compute using manual calls
In [106]: tmp1 = myfunc(a[0],a[1])
...: tmp2 = myfunc(tmp1,a[2])
...: results = myfunc(tmp2,a[3])
# sanity check for equality of both results
In [107]: np.allclose(results, res)
Out[107]: True
P.S。这应该推广到任何N
,其中N = arr.shape[0]
。另外,请注意,由于计算是顺序的,因此没有直接的方法可以并行化它。
答案 1 :(得分:1)
函数的简化版,以及应突出显示操作的a
:
In [344]: def myfunc(x,y):
...: return 2*x + y
...: a = np.eye(5)
In [345]: a
Out[345]:
array([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
In [346]: res = myfunc(a[0],a[1])
In [347]: res
Out[347]: array([2., 1., 0., 0., 0.])
In [348]: for i in a[2:]:
...: res = myfunc(res,i)
...:
In [349]: res
Out[349]: array([16., 8., 4., 2., 1.])
Python具有reduce
函数,可将函数重复应用于列表。在Py3中,这是在functools
中:
In [355]: functools.reduce(myfunc, a)
Out[355]: array([16., 8., 4., 2., 1.])
或者以零res
开头,然后应用于整个数组:
In [357]: res = np.zeros(a.shape[1])
In [358]: for i in a:
...: res = myfunc(res,i)
...:
In [359]: res
Out[359]: array([16., 8., 4., 2., 1.])
要保存中间结果:
In [361]: res = [np.zeros(a.shape[1])]
...: for i in a:
...: temp = myfunc(res[-1],i)
...: res.append(temp)
In [362]: res
Out[362]:
[array([0., 0., 0., 0., 0.]),
array([1., 0., 0., 0., 0.]),
array([2., 1., 0., 0., 0.]),
array([4., 2., 1., 0., 0.]),
array([8., 4., 2., 1., 0.]),
array([16., 8., 4., 2., 1.])]
这是accumulate
的概念。 numpy
ufunc
同时具有reduce
和accumulate
,如果可以与myfunc
一起写入,则速度会更快。但这在一般情况下不起作用。
In [363]: np.add.accumulate(a,axis=0)
Out[363]:
array([[1., 0., 0., 0., 0.],
[1., 1., 0., 0., 0.],
[1., 1., 1., 0., 0.],
[1., 1., 1., 1., 0.],
[1., 1., 1., 1., 1.]])