Reputation: 113
I have a vector of numbers (here random). I'd like to calculate the consecutive relation of something (here means to clarify example) on the left and right side of each number in a vector.
Here is a procedural example. I'm interested in the vectorized form.
from numpy.random import rand
import numpy as np
numbers = rand(40)
k=np.zeros(numbers.shape)
for i in range(*numbers.shape):
k[i]=np.mean(numbers[:i])/np.mean(numbers[i:])
This example will return nan in the first iteration but it is not a problem now.
Upvotes: 1
Views: 41
Reputation: 113
I spent some time and there is a simple and universal solution: numpy.vectorize with excluded
parameter, where vector designated to be split must be excluded from vectorisation. The example still uses np.mean but can be replaced with any function:
def split_mean(vect,i):
return np.mean(vect[:i])/np.mean(vect[i:])
v_split_mean = np.vectorize(split_mean)
v_split_mean.excluded.add(0)
numbers = np.random.rand(30)
indexes = np.arange(*numbers.shape)
v_split_mean(numbers,indexes)
Upvotes: 0
Reputation: 221674
Here's a vectorized way -
n = len(numbers)
fwd = numbers.cumsum()/np.arange(1,n+1)
bwd = (numbers[::-1].cumsum()[::-1])/np.arange(n,0,-1)
k_out = np.r_[np.nan,fwd[:-1]]/bwd
Optimizing a bit further with one cumsum
, it would be -
n = len(numbers)
r = np.arange(1,n+1)
c = numbers.cumsum()
fwd = c/r
b = c[-1]-c
bwd = np.r_[1,b[:-1]]/r[::-1]
k_out = np.r_[np.nan,fwd[:-1]]/bwd
Upvotes: 1