4

MWE: Let us consider the following example.

L0=[[b,0],[b,b]], L1=[[b,b],[b,1]], L2=[[b,b],[2,b]]

S=[[0,1,2],[2,0,1]] 

Is there any way the replace each element of S by L0 for 0 and L1 for 1 and L2 for 2 in S to get S1 like in the image? enter image description here

Actually, I want a python program which will check: if the element of S is zero then it will replace 0 by the predefined 2D array and so on.

4
  • SO is not a "make me software service" Commented Jan 2, 2018 at 17:41
  • It is not an answer! @Netwave Commented Jan 2, 2018 at 17:45
  • So, how many such L- arrays do you have in your actual use case? Commented Jan 2, 2018 at 18:03
  • @Divakar: There are three L-arrays, but size of S is very large. Here I have shown small size of S. Commented Jan 4, 2018 at 2:06

2 Answers 2

5

Yes. We can first construct a numpy array that contains L0, L1 and L2:

A = np.array([L0, L1, L2])

Next we construct a numpy array of S:

B = np.array(S)

now we have for C = A[B] (or C = np.take(A,B,axis=0) as suggested by @Divakar):

>>> C = np.take(A,B,axis=0)
>>> C
array([[[[b, 0],
         [b, b]],

        [[b, b],
         [b, 1]],

        [[b, b],
         [2, b]]],


       [[[b, b],
         [2, b]],

        [[b, 0],
         [b, b]],

        [[b, b],
         [b, 1]]]])

This is of course not exactly what we intended: we want to obtain a 2D-array. We can do this by first transposing (or swapaxes, like @PaulPanzer suggests) and then reshaping, we obtain:

>>> C.transpose(0,2,1,3).reshape(4,6)
array([[b, 0, b, b, b, b],
       [b, b, b, 1, 2, b],
       [b, b, b, 0, b, b],
       [2, b, b, b, b, 1]])

Since 4 and 6 of course depend on the size of the dimensions of L0, L1, L2 and S, we can also calculate them based on that size:

A = np.array([L0, L1, L2])
B = np.array(S)
m, n = B.shape
_, u, v = A.shape
np.take(A,B,axis=0).swapaxes(1,2).reshape(u*m, v*n)

Like @DSM says, from Numpy-1.13, there is np.block function for this purpose, and we can write it as:

>>> np.block([[A[i] for i in row] for row in S])
array([[b, 0, b, b, b, b],
       [b, b, b, 1, 2, b],
       [b, b, b, 0, b, b],
       [2, b, b, b, b, 1]])
Sign up to request clarification or add additional context in comments.

8 Comments

Thank you for your answer. Is it sophisticated process if the dimension of S is large, suppose 400x500? @Willem Van Onsem
@MKS Why don't you try and you will see if it is a "sophisticated process"... [whatever you might mean by "sophisticated process"]
@AGN Gazer: I mean, is there any other way which can do the same thing quickly. May I use bmat for this
Instead of transpose(0,2,1,3), swapaxes(1,2) is perhaps slightly more readable. Still, very nice answer.
While the listcomp isn't nearly as clean as A[B], I think np.block([[A[i] for i in row] for row in S]) (in numpy 1.13) is so much cleaner than the reshape that I'd go that direction.
|
1

If the number of distinct building blocks Li is not large we can use the Kronecker product np.kron:

import numpy as np

L0=[[b,0],[b,b]]; L1=[[b,b],[b,1]]; L2=[[b,b],[2,b]]

S=[[0,1,2],[2,0,1]] 

S1 = sum(np.kron(np.equal(i, S), L) for i, L in enumerate((L0, L1, L2)))

Value of S1 assuming b = 3:

[[3 0 3 3 3 3]
 [3 3 3 1 2 3]
 [3 3 3 0 3 3]
 [2 3 3 3 3 1]]

Comments

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.