2

I have seen this, but it doesn't quite answer my question.

I have an array:

x = np.array([0, 1, 2])

I want this:

y = np.array([[0,1], [0,2], [1,0], [1,2], [2,0], [2,1]])

That is, I want to take each value (let's call it i) of the array x and create x.shape[0]-1 new arrays with all of the other values of x, excluding i.

Essentially y contains the indices of a 3x3 matrix without any diagonal elements.

I have a feeling there's an easy, pythonic way of doing this that's just not coming to me.

2 Answers 2

1

Approach #1 : One approach would be -

x[np.argwhere(~np.eye(len(x),dtype=bool))]

Approach #2 : In two steps -

r = np.arange(len(x))
out = x[np.argwhere(r[:,None]!=r)]

Approach #3 : For performance, it might be better to create those pairwise coordinates and then mask. To get the paiwise coordinates, let's use cartesian_product_transpose, like so -

r = np.arange(len(x))
mask = r[:,None]!=r
out = cartesian_product_transpose(x,x)[mask.ravel()]

Approach #4 : Another with np.broadcast_to that avoids making copies until masking, again meant as a performance measure -

n = len(x)
r = np.arange(n)
mask = r[:,None]!=r
c0 = np.broadcast_to(x[:,None], (n, n))[mask]
c1 = np.broadcast_to(x, (n,n))[mask]
out = np.column_stack((c0,c1))

Runtime test -

In [382]: x = np.random.randint(0,9,(1000))

# @tom10's soln
In [392]: %timeit list(itertools.permutations(x, 2))
10 loops, best of 3: 62 ms per loop

In [383]: %%timeit
     ...: x[np.argwhere(~np.eye(len(x),dtype=bool))]
100 loops, best of 3: 11.4 ms per loop

In [384]: %%timeit
     ...: r = np.arange(len(x))
     ...: out = x[np.argwhere(r[:,None]!=r)]
100 loops, best of 3: 12.9 ms per loop

In [388]: %%timeit
     ...: r = np.arange(len(x))
     ...: mask = r[:,None]!=r
     ...: out = cartesian_product_transpose(x,x)[mask.ravel()]
100 loops, best of 3: 16.5 ms per loop

In [389]: %%timeit
     ...: n = len(x)
     ...: r = np.arange(n)
     ...: mask = r[:,None]!=r
     ...: c0 = np.broadcast_to(x[:,None], (n, n))[mask]
     ...: c1 = np.broadcast_to(x, (n,n))[mask]
     ...: out = np.column_stack((c0,c1))
100 loops, best of 3: 6.72 ms per loop
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! Is this scalable, as seems to be suggested by tom10?
@StatsSorceress Should be!
@StatsSorceress Added timings for all posted approaches on a 1000 elems array.
0

This is a case where, unless you really need to speed, etc, of numpy, pure Python gives a cleaner solution:

import itertools

y = itertools.permutations([0, 1, 2], 2)

# [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]

1 Comment

Thanks! I prefer scalable solutions, as this was just an MWE.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.