0

I have a 2d numpy array with shape - (20,1200) e.g. 24000 pixels, with values of zeros and ones. I want to iterate with blocks of (4,60) and sum the percentage of one's per block, meaning - ((number_of_ones)/240)*100. The result should be injected to a new numpy table (5X20) as each cell represents (4X60) from the original table. Currently, I'm using 2 nested for loops, but it takes time and not best practice.

final_seg = []
for i in range(0, 20, 4):
        for j in range(0, 1200, 60):
            # slice segment from table
            data = big_table[i:i + 4, j:j + 60]
            n_zeros = np.count_nonzero(data == 1)
            final_seg.append((n_zeros/240) * 100)
return final_seg

What's the equivalent with numpy commands?

CS student
  • 33
  • 1
  • 1
  • 4

1 Answers1

0

Quite a performant solution is to create a temporary 4 dimensional view of blocks of initial array and apply np.count_nonzero for both of its axes:

window = (4, 60) 
shape = (big_table.shape[0]//window[0], window[0], big_table.shape[1]//window[1], window[1])
out = np.count_nonzero(big_table.reshape(shape), axis=(1, 3))
mathfux
  • 5,759
  • 1
  • 14
  • 34
  • Wonderful solution. It works perfectly. @mathfux can you please explain how does the axis(1,3) work in this case? – CS student Dec 30 '21 at 19:05
  • @CSstudent After long time spent on this problem, I'm still unable to understand the process completely. I have opened [a related question](https://stackoverflow.com/questions/70444407/why-is-4d-realisation-of-max-pooling-in-numpy-misleading) few days ago. You might find more details about usage of `np.reshape` in conjuction with any 1D to 0D (vector to scalar) operation on `axis=(1, 3)`. I'll come back with an answer once it gets clear. – mathfux Dec 30 '21 at 22:57