This function takes a list/array of booleans and converts them to an array that counts the number of either True/False values found next to each other.
I'd like to see this optimized for performance. It's not too slow, but I do use multiple loops with embedded if-else statements, I'm wondering if they're absolutely necessary.
import numpy as np
x = np.random.uniform(1,100,100)
b = x > x.mean()
#function start, input is b
endarray = []
count = 0
instance = True
while True:
subarray = 0
while True:
if count >= len(b):
endarray.append(subarray)
break
if b[count] == instance:
subarray += 1
count += 1
else:
endarray.append(subarray)
instance = not instance
break
if count >= len(b):
break
if len(endarray) % 2 != 0:
endarray = np.append(endarray, 0)
else:
endarray = np.asarray(endarray)
endarray = endarray.reshape(-1,2)
The output is a Nx2 array, where the left-hand values are always a count of Trues, and the right-hand values are always a count of Falses.
After a sequence of False values are no longer continuous(a True value pops up), the next count of True values begin, and vice versa.
Example input
b
Out[31]:
array([ True, True, True, False, True, True, True, True, False,
False, True, False, False, True, False, False, False, False,
True, False, False, False, True, True, True, True, False,
False, True, False, False, False, False, False, False, True,
True, False, True, True, False, False, True, False, False,
True, False, False, True, False, True, False, True, False,
True, True, True, False, True, False, True, True, True,
True, False, False, True, False, True, True, True, True,
True, True, False, True, True, False, True, True, False,
False, True, False, True, False, False, True, True, True,
True, False, False, False, False, False, True, True, True,
True])
Example output
endarray
Out[32]:
array([[3, 1],
[4, 2],
[1, 2],
[1, 4],
[1, 3],
[4, 2],
[1, 6],
[2, 1],
[2, 2],
[1, 2],
[1, 2],
[1, 1],
[1, 1],
[1, 1],
[3, 1],
[1, 1],
[4, 2],
[1, 1],
[6, 1],
[2, 1],
[2, 2],
[1, 1],
[1, 2],
[4, 5],
[4, 0]])
Edit: I wanted to add an updated version of this code, the one in the answer below is not technically correct in all regards. But this was entirely derived from it:
m = np.append(b[0], np.diff(b))
_, c = np.unique(m.cumsum(), return_index=True)
out = np.diff(np.append(c, len(b)))
if b[0] == False:
out = np.append(0, out)
if len(out) % 2:
out = np.append(out, 0)
out = out.reshape(-1, 2)