我正在从应用于1d numpy数组(包含条件)的函数创建2d numpy数组,并且想知道一种更有效的方法。目前,这是我代码中最慢的部分。 x是1d numpy数组,输出是2d numpy数组。有一个开关可以根据x小于还是大于0构造一个不同的数组元素。将来,开关的数量可以是任意的。
def basis2(x) :
final = []
for i in x :
if i > 0 :
xr = 2.0*(i-0.5)
final.append(np.array([0.0, 0.0, 0.0, 0.5*xr*(xr-1.0),-1.0*(xr+1)*(xr-1), 0.5*xr*(xr+1.0)]))
else :
xl = 2.0*(i+0.5)
final.append(np.array([0.5*xl*(xl-1.0),-1.0*(xl+1)*(xl-1),0.5*xl*(xl+1.0),0.0,0.0,0.0]))
return np.array(final)
理想情况下,我可以消除for循环-但是到目前为止,我还没有设法正确地做到这一点,例如使用“ where”。谢谢您的帮助。
答案 0 :(得分:1)
具有您的功能
In [247]: basis2(np.array([1,.5,0,-.5,-1]))
Out[247]:
[array([ 0., 0., 0., 0., -0., 1.]),
array([ 0., 0., 0., -0., 1., 0.]),
array([ 0., -0., 1., 0., 0., 0.]),
array([-0., 1., 0., 0., 0., 0.]),
array([ 1., 0., -0., 0., 0., 0.])]
In [248]: %hist 245
basis2_1(np.array([1,.5,0,-.5,-1]))
有一些肤浅的变化:
def basis2_1(x) :
xr = 2.0*(x[x>0]-0.5)
res1 = np.array([0.0*xr, 0.0*xr, 0.0*xr, 0.5*xr*(xr-1.0),-1.0*(xr+1)*(xr-1), 0.5*xr*(xr+1.0)])
xl = 2.0*(x[x<=0]+0.5)
res2 = np.array([0.5*xl*(xl-1.0),-1.0*(xl+1)*(xl-1),0.5*xl*(xl+1.0),0.0*xl,0.0*xl,0.0*xl])
return res1, res2
In [250]: basis2_1(np.array([1,.5,0,-.5,-1]))
Out[250]:
(array([[ 0., 0.],
[ 0., 0.],
[ 0., 0.],
[ 0., -0.],
[-0., 1.],
[ 1., 0.]]),
array([[ 0., -0., 1.],
[-0., 1., 0.],
[ 1., 0., -0.],
[ 0., 0., -0.],
[ 0., 0., -0.],
[ 0., 0., -0.]]))
加入两个子数组:
In [251]: np.hstack(_)
Out[251]:
array([[ 0., 0., 0., -0., 1.],
[ 0., 0., -0., 1., 0.],
[ 0., 0., 1., 0., -0.],
[ 0., -0., 0., 0., -0.],
[-0., 1., 0., 0., -0.],
[ 1., 0., 0., 0., -0.]])
显然,这需要改进,但这足以让您入门。
例如,您可以制作一个result = np.zeros((5,x.shape[0]))
数组,只需插入相应的非零元素(保存所有这些0.0*xr
项)。
查看Out[251]
中的那些块:
In [257]: x = np.array([1,.5,0,-.5,-1])
In [258]: Out[251][3:,np.nonzero(x>0)[0]]
Out[258]:
array([[ 0., -0.],
[-0., 1.],
[ 1., 0.]])
In [259]: Out[251][:3,np.nonzero(x<=0)[0]]
Out[259]:
array([[ 0., -0., 1.],
[-0., 1., 0.],
[ 1., 0., -0.]])
答案 1 :(得分:1)
这是利用对称性的矢量化方法:
col = np.s_[...,None]
def basis2_v(x):
h,w = np.arange(x.size)[col],np.arange(3,dtype=np.int8)
# if the terms for xr are the same as the formulas for xl applied to -xr
# we can therefore unify the code and apply it to |x|:
# there are three factors in total each term consists of two of them
aux = (np.abs(x[col])-w/2)*(2/(1^-(w&1)))
# the easiest is multiplying all three and then dividing one out again
aux = -aux.prod(-1)[col]/aux
# fix degenerate cases
aux[np.isnan(aux)] = 1
# finally, we need to embed the terms in a zero matrix
out = np.zeros((x.size,6),x.dtype)
# the xor trick maps 2,1,0 to -3,-2,-1 if x>0
out[h,(-(x[col]>0).view(np.int8))^w[::-1]] = aux
return out
# make small test
x = np.random.randn(10)
# this should pass
assert np.allclose(basis2(x),basis2_v(x))