Python Numpy:基于上一个元素计算?
假设我有数组Python Numpy:基于上一个元素计算?,python,numpy,Python,Numpy,假设我有数组x和y: x = numpy.array([1,2,3,4,5,6,7,8,9,10]) # actual content is the a result of another calculation step 对于y,有一个公式,每个元素基于前面的元素,让i表示y的索引,每个元素是: y[i] = y[i-1] * 2 + x[i] 计算第一个元素时,让y[i-1]=50。换句话说,y应该是: [101, 204, 411, 826, 1657, 3320, 6647, 13
x
和y
:
x = numpy.array([1,2,3,4,5,6,7,8,9,10]) # actual content is the a result of another calculation step
对于y
,有一个公式,每个元素基于前面的元素,让i
表示y
的索引,每个元素是:
y[i] = y[i-1] * 2 + x[i]
计算第一个元素时,让y[i-1]=50
。换句话说,y
应该是:
[101, 204, 411, 826, 1657, 3320, 6647, 13302, 26613, 53236]
如何使用numpy计算
y
x = [1, 2, 3, 4, 5, 6, 7, 8 ,9, 10]
y = [50]
for i in range(len(x)):
y.append(y[-1] * 2 + x[i])
y = y[1:]
如果您需要递归计算,如果您的
y[i]
应该依赖于同一次运行中计算的y[i-1]
,那么numpy中似乎没有内置的解决方案,那么您可能希望从最后一个元素开始计算它,以防止在下一次i
中使用新值,您需要使用一个简单的for
循环来计算它:
y = np.empty(x.size)
last = 50
for i in range(x.size):
y[i] = last = last * 2 + x[i]
见这个问题:
否则,可以使用numpy在一行中实现公式:
y = np.concatenate(([50], y[:-1])) * 2 + x
说明:
y[:-1]
创建一个N-1
大小的数组:y\u 0,y\u 1。。。y\u N-1
np.concatenate(([50], y[:-1]))
创建一个N
大小的数组,第一个元素的起始值为50。所以这个表达式基本上就是你的y[i-1]
然后,您可以使用numpy数组算术进行数学元素分析。让我们在序列中构建一些项:
y[0] = 2*y[-1] + x[0]
y[1] = 2*y[0] + x[1] = 4*y[-1] + 2*x[0] + x[1]
y[2] = 2*y[1] + x[2] = 8*y[-1] + 4*x[0] + 2*x[1] + x[2]
...
y[n] = 2**(n+1)*y[-1] + 2**n*x[0] + 2**(n-1)*x[1] + ... + x[n]
这可能不是很明显,但您可以使用numpy构建上述序列,例如:
n = len(x)
y_1 = 50
pot = 2**np.arange(n-1, -1, -1)
y = np.cumsum(pot * x) / pot + y_1 * 2**np.arange(1, n+1)
>>> y
array([ 101, 204, 411, 826, 1657, 3320, 6647, 13302, 26613, 53236])
这种解决方案的缺点是它们不是很通用:问题中的一个小变化可能会使整个方法变得无用。但是,只要你能用一点代数来解决一个问题,它几乎肯定会远远超过任何算法方法。这是如何用numpy来解决的:
import numpy as np
x = np.array([ 1, 2, 3, 4, 5, 6, 7, 8 ,9, 10 ])
y = np.array([ 50 ])
for i in np.arange(len(x)):
y = np.append(
y,
( y[-1] * 2 + x[i] )
)
y = y[1:]
print(y)
也许最快、最简洁的方法是使用,它完全实现了您描述的递归关系:
from scipy.signal import lfilter
import numpy as np
x = np.array([1,2,3,4,5,6,7,8,9,10])
b = [1., 0.]
a = [1., -2.]
zi = np.array([2*50]) # initial condition
y, _ = lfilter(b, a, x, zi=zi)
结果将是np.float64
,但如果需要,您可以强制转换为例如np.int32
:
>>> y.astype(np.int32)
array([ 101, 204, 411, 826, 1657, 3320, 6647, 13302, 26613, 53236])
y
的起始值是多少,即y[0]
?有一个人为的起始值50。你写的代码怎么了?@moose,这只是伪代码,不是numpy。这是一个非齐次线性递归方程。你有没有考虑过先找到解析解,然后看看它是否能被有效地编码?很好!然后更改y
的第一个元素。输出不应该是[101、204、411、826、1657、3320、6647、13302、26613、53236]
?和第二个元素不匹配?应该是204,而不是102这似乎不能正确处理复发。它看起来是为了从一个旧的y
和x
构建一个全新的y
数组而设计的,而期望的行为似乎是将给定的关系保存在一个y
数组中;期望的结果是这个解决方案的一个固定点。好吧,我想我当时误解了要求。如果OP想要一个递归公式,这个答案对他来说是行不通的。(当我写这个答案时,没有示例结果)实际上,我想要的是递归的,我没有意识到这一点,我希望numpy能够通过一些神奇的切片实现这一点。谢谢你的解释。我将继续使用for循环。我假设“如何使用numpy计算*”意味着一个有效的矢量化版本。@AmiTavory显然不是。我在评论中问过他的代码有什么问题,答案是“这是伪代码”。但我也认为费迪南德·拜尔斯的答案应该是被接受的答案(并获得了更高的票数),它甚至更简单,比如y=[50*2+x[0];对于x[1:]:y.append(y[-1]*2+v)
而您的解决方案还不正确。嗯。。。我的意思是这是伪代码,要转换成numpy。我想我很清楚我想要一个numpy解决方案。然后你可以简单地将我这里的代码块复制到你的问题中,然后说你想要相同的结果,但是使用矢量化/高效的numpy解决方案。numpy.cumsum()
比使用for
循环快很多,对于我的测试应用程序快约8倍。