The Python Oracle

numpy 2d boolean array count consecutive True sizes

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Magical Minnie Puzzles

--

Chapters
00:00 Numpy 2d Boolean Array Count Consecutive True Sizes
00:35 Accepted Answer Score 3
01:22 Thank you

--

Full question
https://stackoverflow.com/questions/4977...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #numpy #boolean #floodfill

#avk47



ACCEPTED ANSWER

Score 3


Here's a quick and simple complete solution:

import numpy as np
import scipy.ndimage.measurements as mnts

A = np.array([
    [1, 0, 0, 0],
    [0, 1, 1, 0],
    [0, 1, 0, 0],
    [0, 1, 0, 0]
])

# labeled is a version of A with labeled clusters:
#
# [[1 0 0 0]
#  [0 2 2 0]
#  [0 2 0 0]
#  [0 2 0 0]]
#
# clusters holds the number of different clusters: 2
labeled, clusters = mnts.label(A)

# sizes is an array of cluster sizes: [0, 1, 4]
sizes = mnts.sum(A, labeled, index=range(clusters + 1))

# mnts.sum always outputs a float array, so we'll convert sizes to int
sizes = sizes.astype(int)

# get an array with the same shape as labeled and the 
# appropriate values from sizes by indexing one array 
# with the other. See the `numpy` indexing docs for details
labeledBySize = sizes[labeled]

print(labeledBySize)

output:

[[1 0 0 0]
 [0 4 4 0]
 [0 4 0 0]
 [0 4 0 0]]

The trickiest line above is the "fancy" numpy indexing:

labeledBySize = sizes[labeled]

in which one array is used to index the other. See the numpy indexing docs (section "Index arrays") for details on why this works.

I also wrote a version of the above code as a single compact function that you can try out yourself online. It includes a test case based on a random array.