Sam-gege
Sam-gege

Reputation: 819

Python Numpy: reverse transpose

suppose I have an array of shape (2,2,3): x=np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]), and I have transposed this array to y along axes (2,0,1): y=np.transpose(x,(2,0,1)).

My questions is, how to transpose y back to x? I know I can use np.transpose(y,(1,2,0)) to change back to x, but I'd like to have a neat way of finding that correct axes (1,2,0).

Thanks for any help!

Upvotes: 4

Views: 347

Answers (2)

hamflow
hamflow

Reputation: 319

I just answered a quite similar question in another topic in which I produced two useful functions (see the codes):

Let me first clearly explain how to calculate permutation argument: For example, imagine if we want to get permutation argument of transposing an array of size (i, j, k) into (k, i, j). To calculate the permutation argument, first you must number each axis pythonically, so in given example: "i" is axis=0, "j" is axis =1, and "k" is axis=2. Then, you should maintain original axis numbers and arrange those numbers into final desired axes arrangement, as in: "i" should be placed in axis=1 and "i" was represented by number 0 so 0 sits in position of axis=1 which gives => ( ?, 0, ?), and by maintaining the same condition for other axes the permutation argument of (2,0,1) will be obtained. However, It is easy to mistake final axis numbers instead of the original ones in calculating the permutation argument, like mistakenly considering: "i" should become axis=1, "j" should become axis=2, and "k" should become axis=0, which gives wrong value of (1, 2, 0). In some cases, even if you choose the second method (the wrong one) you might end up getting the right answer if rearrangement change is symmetrical from point of view of a middle axis which splits axes equally (in 3 dimension it is axis=1 but for example in 4 dimension it is an imaginary axis between axis=1 and axis=2), for example if you want to reshape (a, b, c) into (c,b,a), both methods yield permutation argument of (2, 1, 0). So, it is easy to think your wrong method is right and wonder why it does not work for some specific reshapes!

In your example, you changed an array of size (i, j ,k) by permutation number of (2, 0, 1), so by maintaining number of axes according to what has been said above we'll have: (i=0, j=1 ,k=1) so final arrangement (=permutation argument) of (2, 0, 1) gives: (2= k, 0=i, 1=j). now your new array has size of (k, i, j). Then again, you want to transpose (k, i, j) back into (i, j, k). so by updating axes for each dimension we'll have: (k=0, i=1, j=2), thus axes arrangement of (i, j, k) produces (i=1, j=2, k=0) or simply as (1, 2, 0).

I automated this procedure below. However, I don't think it is really necessary because these rare cases in reshaping arrays can be easily calculated by yourself when you know the correct method):

# functions to produce shape of transposed array after permutation and the permutation argument 
import numpy as np

def permutation_result(a_,p):
    """
    returns transposed shape of array "a" when permutation argument is given
    a_ = np.shape(a) ; p = permutation argument
    """

    le = len(a_)  # number of dimensions
    dim = np.zeros(le)
    for q in range(le):
        dim[q] = a_[q]
    axes = np.zeros((le,2))
    for q in range(le):
        axes[q][0] = dim[q]
        axes[q][1] = q
    b_ = np.zeros(le) # b sizes
    for m in range(le):
        b_[m] = axes[np.argwhere(axes==p[m])[0,0]][0] # only rows are important
    return b_



def permutation_arg(a_,b_):
    """
    returns permutation argument when array "a" is transposed into array "b"
    a_ = np.shape(a) ; b_ = np.shape(b)
    """
    a_ = np.shape(a)
    le = len(a_)  # number of dimensions
    dim = np.zeros(le)
    for q in range(le):
        dim[q] = a_[q]
    axes = np.zeros((le,2))
    for q in range(le):
        axes[q][0] = dim[q]
        axes[q][1] = q
    p = np.zeros(le) # b sizes
    for m in range(le):
        p[m] = axes[np.argwhere(axes==b_[m])[0,0]][1] # only columns are important
    return p

# given example (tranposing array "a" by a given permutation argument 
# and finding second permution argument for transposing it back to the original array again)
i = 25
j = 32
k = 11
a = np.random.rand(i,j,k) 
a_ = np.shape(a)  # initial shape
p1 = [2,0,1] # first permutation argument
b_ = permutation_result(a_,p1) # transposed shape
print(f'shape of transposed array = {b_}')
p2 = permutation_arg(np.transpose(a,(p1)),a_) # second permutation argument
print(f'second permutation argument = {p2}')

# which gives:
# shape of transposed array = [11. 25. 32.]
# second permutation argument = [0. 1. 2.]

Upvotes: 0

bb1
bb1

Reputation: 7873

You can use

np.argsort((2, 0, 1))

It gives:

array([1, 2, 0])

It will work with any permutation of axes.

Upvotes: 4

Related Questions