Count Consecutive Occurences of Values Varying in Length in a Numpy Array

Count consecutive occurences of values varying in length in a numpy array

Here's a solution using itertools (it's probably not the fastest solution):

import itertools
condition = [True,True,True,False,False,True,True,False,True]
[ sum( 1 for _ in group ) for key, group in itertools.groupby( condition ) if key ]

Out:
[3, 2, 1]

Count consecutive equal values in array

Here is one option adapted from this answer:

def count_consecutive(arr, n):
# pad a with False at both sides for edge cases when array starts or ends with n
d = np.diff(np.concatenate(([False], arr == n, [False])).astype(int))
# subtract indices when value changes from False to True from indices where value changes from True to False
return np.flatnonzero(d == -1) - np.flatnonzero(d == 1)

count_consecutive(a, 5)
# array([2, 1, 3])

Count number of consecutive elements in a list

Here's a simple python script:

arr = [100, 100, 100, 100, 100, 200, 100, 100, 100, 100, 100, 100, 100,
100, 200, 100, 100, 100, 100, 100, 100, 100, 100, 200, 100, 100,
100, 100, 100, 100, 100, 200, 100, 100, 100, 100, 100, 100, 100,
100, 200, 100, 100, 100, 100, 100, 100, 100, 100, 200, 100, 100,
100, 100, 100, 100, 100, 300, 100, 100, 100]

check = arr[0]
result = []
count = 0
for el in arr:
if el == check:
count+=1
else:
check = el
if count>1:
result.append(count)
count = 1
result.append(count)

print(result)
[5, 8, 8, 7, 8, 8, 7, 3]

Count consecutive values within an array with multiple values numpy/pandas

You can also use pd.Series and groupby:

s = pd.Series([1,2,3,3,4,5,6,1,1,1,5,5,8,8,8,9,4,4,4])

print (s.groupby((s!=s.shift()).cumsum()).cumcount() + 1)
#
[1, 1, 1, 2, 1, 1, 1, 1, 2, 3, 1, 2, 1, 2, 3, 1, 1, 2, 3]

Count consecutive occurrences of True value in two dimentional numpy array (matrix) of Booleans

Convert your code applied to each row to the following lambda function:

myCount = lambda ar: [sum(1 for _ in group) for key, group in itertools.groupby(ar) if key]

Then assemble results for each row the following way:

res = []
for i in range(arr.shape[0]):
res.append(myCount(arr[i]))

To test also other cases, I extended your sample data with a row full of
False values and another row full of True:

array([[ True, False,  True,  True,  True],
[False, True, True, False, True],
[False, True, False, False, False],
[ True, True, False, False, True],
[False, False, False, False, False],
[ True, True, True, True, True]])

The result for the above array is:

[[1, 3], [2, 1], [1], [2, 1], [], [5]]

I think, this result should be left as a pythonic nested list.
The reason is that Numpy does not support "jagged" arrays (with
rows of different length).

Find runs and lengths of consecutive values in an array

Find consecutive runs and length of runs with condition

import numpy as np

arr = np.array([0, 3, 0, 1, 0, 1, 2, 1, 2, 2, 2, 2, 1, 3, 4])

res = np.ones_like(arr)
np.bitwise_xor(arr[:-1], arr[1:], out=res[1:]) # set equal, consecutive elements to 0
# use this for np.floats instead
# arr = np.array([0, 3, 0, 1, 0, 1, 2, 1, 2.4, 2.4, 2.4, 2, 1, 3, 4, 4, 4, 5])
# res = np.hstack([True, ~np.isclose(arr[:-1], arr[1:])])
idxs = np.flatnonzero(res) # get indices of non zero elements
values = arr[idxs]
counts = np.diff(idxs, append=len(arr)) # difference between consecutive indices are the length

cond = counts > 2
values[cond], counts[cond], idxs[cond]

Output

(array([2]), array([4]), array([8]))
# (array([2.4, 4. ]), array([3, 3]), array([ 8, 14]))

Find large number of consecutive values fulfilling condition in a numpy array

Here's a numpy-based solution.

I think (?) it should be faster than the other options. Hopefully it's fairly clear.

However, it does require a twice as much memory as the various generator-based solutions. As long as you can hold a single temporary copy of your data in memory (for the diff), and a boolean array of the same length as your data (1-bit-per-element), it should be pretty efficient...

import numpy as np

def main():
# Generate some random data
x = np.cumsum(np.random.random(1000) - 0.5)
condition = np.abs(x) < 1

# Print the start and stop indices of each region where the absolute
# values of x are below 1, and the min and max of each of these regions
for start, stop in contiguous_regions(condition):
segment = x[start:stop]
print start, stop
print segment.min(), segment.max()

def contiguous_regions(condition):
"""Finds contiguous True regions of the boolean array "condition". Returns
a 2D array where the first column is the start index of the region and the
second column is the end index."""

# Find the indicies of changes in "condition"
d = np.diff(condition)
idx, = d.nonzero()

# We need to start things after the change in "condition". Therefore,
# we'll shift the index by 1 to the right.
idx += 1

if condition[0]:
# If the start of condition is True prepend a 0
idx = np.r_[0, idx]

if condition[-1]:
# If the end of condition is True, append the length of the array
idx = np.r_[idx, condition.size] # Edit

# Reshape the result into two columns
idx.shape = (-1,2)
return idx

main()

Finding palindromic sequences of specified length among consecutive array elements - is a non-loopy solution possible?

This answer uses an overt loop and performs extremely well. Average duration is ~250ms (excluding construction of the pseudo-random list)

import random
from datetime import datetime

s = [random.randint(1, 9) for _ in range(1_000_000)]

def pal(n):
r = []
for i in range(len(s) - n + 1):
a = s[i:i + n]
if a == a[::-1]:
r.append(i)
return r

_start = datetime.now()
result = pal(5)
_end = datetime.now()
print(f'Duration={_end-_start}')


Related Topics



Leave a reply



Submit