jarekj71
jarekj71

Reputation: 113

How to vectorize process of spltting vector

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

Answers (2)

jarekj71
jarekj71

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

Divakar
Divakar

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

Related Questions