3
  • Python: get all possible array attributions of nd arrays. Use itertools.product?
    • If so, how?
  • In Python, I have two n dimensions numpy arrays A and B (B is a zero array).
  • Such way A.shape[i]<=B.shape[i], for any i between 0 and n. I want to create a for loop in such way every iteration I attribute A to a different subset of B, in such way every possible position in occupied until the end of the for loop.

for instance, with A = np.array([[1,1,1],[1,1,1]]) and B = np.zeros((3,4)), I would get these(one of these for each iteration):

1 1 1 0       0 1 1 1       0 0 0 0      0 0 0 0
1 1 1 0       0 1 1 1       1 1 1 0      0 1 1 1
0 0 0 0       0 0 0 0       1 1 1 0      0 1 1 1

For a fixed n dimension it is trivial, just use nested for loops for each dimension. However, I want it for a generic n dimensions.

My approach was to use the itertools.product to get all combinations of indexes. In the above example, product([0,1],[0,1]), would iterate over (0,0),(0,1),(1,0),(1,1), and I would have my indexes. However, I don't know how to pass the values of the parameters to product function for a generic n. Any idea? There are better ways of doing so?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
  • 1
    "However, I don't know how to pass the values of the parameters to product function for a generic `n`." Does https://stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters help? – Karl Knechtel Jun 27 '20 at 21:40

3 Answers3

2

itertools product should work.

import numpy as np
from itertools import product

A = np.ones((2,3))
B = np.zeros((3,4))

r_rng = range(B.shape[0]-A.shape[0]+1)
c_rng = range(B.shape[1]-A.shape[1]+1)

for i,j in product(r_rng, c_rng):
    C = B.copy()
    C[i:i+A.shape[0],j:j+A.shape[1]]=A
    print(C,'\n')

Output:

[[1. 1. 1. 0.]
 [1. 1. 1. 0.]
 [0. 0. 0. 0.]]

[[0. 1. 1. 1.]
 [0. 1. 1. 1.]
 [0. 0. 0. 0.]]

[[0. 0. 0. 0.]
 [1. 1. 1. 0.]
 [1. 1. 1. 0.]]

[[0. 0. 0. 0.]
 [0. 1. 1. 1.]
 [0. 1. 1. 1.]]
LevB
  • 925
  • 6
  • 10
  • This example is for a 2D array, in a nD, we would have to use n 'range(B.shape[i]-A.shape[i]+1)' expressions as params of product function. And is that that i dont know how to do... – Jonathan alis Jun 28 '20 at 04:33
1

Here is an example. You can use the * operator to unpack a variable number of argument from a list and give it to itertools.product():

import itertools

size1 = (3,5,6)
size2 = (2,2,2)
N = len(size1)
coords = []
for i in range(N):
    delta = size1[i]-size2[i]
    coords.append(list(range(delta)))
    
print(coords)
it = itertools.product(*coords)
arr = np.array(list(it))
print(arr)

Output:

[[0 0 0]
 [0 0 1]
 [0 0 2]
 [0 0 3]
 [0 1 0]
 [0 1 1]
 [0 1 2]
 [0 1 3]
 [0 2 0]
 [0 2 1]
 [0 2 2]
 [0 2 3]]
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
0

Im going to post the solution I obtained:

import numpy as np 
from itertools import product
A=np.ones((2,3,2))
B=np.zeros((3,4,4))
coords=[]
for i in range(len(B.shape)):
    delta = B.shape[i]-A.shape[i]+1
    coords.append(list(range(delta)))
print(coords)
for start_idx in product(*coords):
    idx=tuple(slice(start_idx[i], start_idx[i]+A.shape[i]) for i in range(len(A.shape)))
    m=np.zeros(B.shape)
    m.__setitem__(tuple(idx), A)  
    print(m)

ps: Indexing the nd arrays was very tricky