Numpy: calculated based on the previous item?

Say I have an array of x and y :

 x = numpy.array([1,2,3,4,5,6,7,8,9,10]) # actual content is the a result of another calculation step 

There is a formula for y , and each element is based on the previous element, let i denote the index y , each element:

 y[i] = y[i-1] * 2 + x[i] 

When computing the first element, let y[i-1] = 50 . In other words, y should be:

 [101, 204, 411, 826, 1657, 3320, 6647, 13302, 26613, 53236] 

How to calculate y with numpy?

+6
source share
5 answers

Let's build some elements in your sequence:

 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] 

This may not be immediately obvious, but you can build the above sequence with numpy by doing something like:

 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]) 

The downside of this type of solution is that it is not very general: a small change in your problem can make the whole approach useless. But whenever you can solve a problem with a little algebra, it will almost certainly surpass any algorithmic approach with great returns.

+4
source

If you need a recursive calculation, if your y[i] should depend on the calculated y[i-1] on the same run, then there seems to be no built-in solution in numpy, and you will need to calculate it using a simple for loop :

 y = np.empty(x.size) last = 50 for i in range(x.size): y[i] = last = last * 2 + x[i] 

See this question: Is the "for" "loop if the elements of the numpy vector depend on the previous element?

Otherwise, you can implement your formula on a single line using numpy:

 y = np.concatenate(([50], y[:-1])) * 2 + x 

Explanation:

 y[:-1] 

Creates an N-1 array: y_0, y_1, ... y_N-1 .

 np.concatenate(([50], y[:-1])) 

Creates an array of size N with the first element of your initial value of 50. So this expression is basically your y[i-1] .

Then you can use the math element using the arithmetic of a numpy array.

+4
source

Here's how to do it with 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) 
0
source

Perhaps the quickest and shortest way is to use scipy.signal.lfilter , which implements exactly the type of recursive relationships that you described:

 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) 

The result will be np.float64 , but you can lead, for example, to np.int32 if this is what you need:

 >>> y.astype(np.int32) array([ 101, 204, 411, 826, 1657, 3320, 6647, 13302, 26613, 53236]) 
0
source

Here's how you do it with Python:

 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:] 

You might want to calculate it from the last element in order to prevent the use of new values ​​for the next i .

-1
source

Source: https://habr.com/ru/post/986626/


All Articles