1

How can I (efficiently) get each combination of a group of 1D-arrays into a 2D array? Let's say I have arrays A, B, C, and D and I want to create a 2D array with each combination such that I would have 2D arrays that represent AB, AC, AD, ABC, ABD, ..., CD.

For clarity on my notation above:

A = np.array([1,2,3,4,5])
B = np.array([2,3,4,5,6])
C = np.array([3,4,5,6,7])

so

AB = np.array([1,2,3,4,5], [2,3,4,5,6])
ABC = np.array([1,2,3,4,5], [2,3,4,5,6],[3,4,5,6,7])

So far I have tried something like:

A = np.array([1,2,3,4,5])
B = np.array([2,3,4,5,6])
C = np.array([3,4,5,6,7])
D = np.array([4,5,6,7,8])

stacked = np.vstack((A,B,C,D), axis=0)
combos = []
it2 = itertools.combinations(range(4), r=2)
for i in list(it2):
    combos.append(i)
it3 = itertools.combinations(range(4), r=3)
for i in list(it3):
    combos.append(i)
it4 = itertools.combinations(range(4), r=4)
for i in list(it4):
    combos.append(i)

which gets me a list of all the possible combos. then I can apply something like:

for combo in combos:
    stacked[combo,:]
    #Then I do something with each combo

And this is where I get stuck This is fine when it's only A,B,C,D but if I have A,B,C,... X,Y,Z then the approach above doesn't scale as I'd have to call itertools 20+ times. How can I overcome this and make it more flexible (in practice the number of arrays will likely be 5-10)?

1
  • for r in range(1:21): #etc.? The code that you have seems to be manually looping over r -- just make it a proper loop. Commented May 10, 2021 at 10:32

4 Answers 4

2

As others have also recommended, use itertools.combinations

import numpy as np

from itertools import combinations

A = np.array([1,2,3,4,5])
B = np.array([2,3,4,5,6])
C = np.array([3,4,5,6,7])

arrays = [A, B, C]

combos = []
for i in range(2, len(arrays) + 1):
    combos.extend(combinations(arrays, i))

for combo in combos:
    arr = np.vstack(combo)  # do stuff with array
Sign up to request clarification or add additional context in comments.

Comments

2

You can use an additional outer for-loop:

arrays = np.array([  # let's say your input arrays are stored as one 2d array
    [1, 2, 3, 4, 5],
    [2, 3, 4, 5, 6],
    ...
])

combos = []
for r in range(2, len(arrays)+1):
    combos.extend(it.combinations(range(len(arrays)), r=r))

Comments

1

When you have N items, there are 2^N combinations, so this will take 2^N iterations.

You can go through these 2^N iterations with a single loop if you use a for loop for the range 0 <= n < (2^N) and use bitwise operations to select the items from the list of items according the the current n.

Comments

1

You could try this:

from itertools import combinations

A = np.array([1,2,3,4,5])
B = np.array([2,3,4,5,6])
C = np.array([3,4,5,6,7])

lst = [A,B,C]
[list(combinations(lst, i)) for i in range(1,len(lst)+1)]

out:

# [[(array([1, 2, 3, 4, 5]),),
#   (array([2, 3, 4, 5, 6]),),
#   (array([3, 4, 5, 6, 7]),)],
#  [(array([1, 2, 3, 4, 5]), array([2, 3, 4, 5, 6])),
#   (array([1, 2, 3, 4, 5]), array([3, 4, 5, 6, 7])),
#   (array([2, 3, 4, 5, 6]), array([3, 4, 5, 6, 7]))],
#  [(array([1, 2, 3, 4, 5]), array([2, 3, 4, 5, 6]), array([3, 4, 5, 6, 7]))]]

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.