Let's say I have a binary vector representing two phases:
signal = np.array([0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1])
I would like to compute, for each value of this vector, its "position" relative to its chunk, expressed, for instance, in percentage such as follows:
desired output:
[0, 0.33, 0.66, 0.99,
0, 0.5, 1,
0, 1,
0, 0.33, 0.66, 0.99]
I wonder what is the most efficient or pythonic way of obtaining that. One way would be to loop back and forth and compute the length of each "phase", and to divide the index accordingly, but that seems quite convoluted?
Thanks a lot :)
There's nothing un-Pythonic about writing loops, but if you absolutely must do everything with comprehensions and itertools
, here's one way:
import numpy as np
from itertools import chain, groupby
signal = np.array([0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1])
result = list(chain.from_iterable(
np.linspace(0, 1, sum(1 for _ in v))
for _, v in groupby(signal)
))
Result (do your own rounding if really necessary):
[0.0, 0.3333333333333333, 0.6666666666666666, 1.0,
0.0, 0.5, 1.0,
0.0, 1.0,
0.0, 0.3333333333333333, 0.6666666666666666, 1.0]
Explanation:
groupby(signal)
groups the contiguous sequences of 0s or 1s,sum(1 for _ in v)
gets the length of the current sequence,np.linspace(0, 1, ...)
creates an array of that length containing evenly-spaced numbers from 0 to 1,list(chain.from_iterable(...))
concatenates those arrays together, into a list.