Home > OS >  Reorder a square array using a sorted 1D array
Reorder a square array using a sorted 1D array

Time:02-16

Let's say I have a symmetric n-by-n array A and a 1D array x of length n, where the rows/columns of A correspond to the entries of x, and x is ordered. Now assume both A and x are randomly rearranged, so that the rows/columns still correspond but they're no longer in order. How can I manipulate A to recover the correct order?

As an example: x = array([1, 3, 2, 0]) and

A = array([[1, 3, 2, 0],
           [3, 9, 6, 0],
           [2, 6, 4, 0],
           [0, 0, 0, 0]])

so the mapping from x to A in this example is A[i][j] = x[i]*x[j]. x should be sorted like array([0, 1, 2, 3]) and I want to arrive at

A = array([[0, 0, 0, 0],
           [0, 1, 2, 3],
           [0, 2, 4, 6],
           [0, 3, 6, 9]])

CodePudding user response:

I guess that OP is looking for a flexible way to use indices that sorts both rows and columns of his mapping at once. What is more, OP might be interested in doing it in reverse, i.e. find and initial view of mapping if it's lost.

def mapping(x, my_map, return_index=True, return_inverse=True):
    idx = np.argsort(x)
    out = my_map(x[idx], x[idx])
    inv = np.empty_like(idx)
    inv[idx] = np.arange(len(idx))
    return out, idx, inv

x = np.array([1, 3, 2, 0])
a, idx, inv = mapping(x, np.multiply.outer) #sorted mapping
b = np.multiply.outer(x, x) #straight mapping

print(b)
>>> [[1 3 2 0]
     [3 9 6 0]
     [2 6 4 0]
     [0 0 0 0]]
print(a)
>>> [[0 0 0 0]
     [0 1 2 3]
     [0 2 4 6]
     [0 3 6 9]]

np.array_equal(b, a[np.ix_(inv, inv)]) #sorted to straight
>>> True
np.array_equal(a, b[np.ix_(idx, idx)]) #straight to sorted
>>> True

CodePudding user response:

A simple implementation would be

idx = np.argsort(x)
A = A[idx, :]
A = A[:, idx]

Another possibility would be (all credit to @mathfux):

A[np.ix_(idx, idx)]

CodePudding user response:

You can use argsort and fancy indexing:

idx = np.argsort(x)
A2 = A[idx[None], idx[:,None]]

output:

array([[0, 0, 0, 0],
       [0, 1, 2, 3],
       [0, 2, 4, 6],
       [0, 3, 6, 9]])
  • Related