Home > other >  Getting a subset of numpy array indicies an easy way
Getting a subset of numpy array indicies an easy way

Time:07-11

Can this for loop be written in a simpler way?

import itertools
import numpy as np

def f(a, b, c):
  print(a b c)

a = np.arange(12).reshape(3, 4)

for y, x in itertools.product(range(a.shape[0]-1), range(a.shape[1]-1)):
  f(a[y, x], a[y, x 1], a[y 1, x])

The other options I tried, look more convoluted, e.g.:

it = np.nditer(a[:-1, :-1], flags=['multi_index'])

for e in it:
  y, x = it.multi_index
  f(a[y, x], a[y, x 1], a[y 1, x])

CodePudding user response:

Posting it as an answer, and sorry if this is too obvious, but isn't this simply

for y in range(a.shape[0]-1):
     for x in range(a.shape[1]-1):
         f(a[y, x], a[y, x 1], a[y 1, x])

CodePudding user response:

If I use you method I got:

expected = [5, 8, 11, 17, 20, 23]

but you can vectorize the computation by generating an array containing the data in a more suitable way:

a_stacked = np.stack([a[:-1, :-1], a[:-1, 1:], a[1:, :-1]], axis=0)

From there multiple solutions:

  • If you already know the function will be the sum:
>>> a_stacked.sum(axis=0)
array([[ 5,  8, 11],
       [17, 20, 23]])
  • If you know that your function is already vectorized:
>>> f(*a_stacked)
array([[ 5,  8, 11],
       [17, 20, 23]])
  • If your function does not vectorize, you can use np.vectorize for convenience (no performance improvement):
>>> np.vectorize(f)(*a_stacked)
array([[ 5,  8, 11],
       [17, 20, 23]])

Obviously you can flatten the array next.

  • Related