aura aura - 3 months ago 7
Python Question

In Python 3, convert np.array object type to float type, with variable number of object element

I have a np.array with dtype as object. Each element here is a np.array with dtype as float and shape as (2,2) --- in maths, it is a 2-by-2 matrix. My aim is to obtain one 2-dimenional matrix by converting all the object-type element into float-type element. This can be better presented by the following example.

dA = 2 # dA is the dimension of the following A, here use 2 as example only
A = np.empty((dA,dA), dtype=object) # A is a np.array with dtype as object
A[0,0] = np.array([[1,1],[1,1]]) # each element in A is a 2-by-2 matrix
A[0,1] = A[0,0]*2
A[1,0] = A[0,0]*3
A[1,1] = A[0,0]*4


My aim is to have one matrix B (the dimension of B is 2*dA-by-2*dA). The form of B in maths should be

B =
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4


If dA is fixed at 2, then things can be easier, because I can hard-code

a00 = A[0,0]
a01 = A[0,1]
a10 = A[1,0]
a11 = A[1,1]
B0 = np.hstack((a00,a01))
B1 = np.hstack((a10,a11))
B = np.vstack((B0,B1))


But in reality, dA is a variable, it can be 2 or any other integer. Then I don't know how to do it. I think nested for loops can help but maybe you have brilliant ideas. It would be great if there is something like cell2mat function in MATLAB. Because here you can see A[i,j] as a cell in MATLAB.

Thanks in advance.

Answer

Here's a quick way.

Your A:

In [137]: A
Out[137]: 
array([[array([[1, 1],
       [1, 1]]), array([[2, 2],
       [2, 2]])],
       [array([[3, 3],
       [3, 3]]), array([[4, 4],
       [4, 4]])]], dtype=object)

Use numpy.bmat, but convert A to a python list first, so bmat does what we want:

In [138]: B = np.bmat(A.tolist())

In [139]: B
Out[139]: 
matrix([[1, 1, 2, 2],
        [1, 1, 2, 2],
        [3, 3, 4, 4],
        [3, 3, 4, 4]])

The result is actually a numpy.matrix. If you need a regular numpy array, use the .A attribute of the matrix object:

In [140]: B = np.bmat(A.tolist()).A

In [141]: B
Out[141]: 
array([[1, 1, 2, 2],
       [1, 1, 2, 2],
       [3, 3, 4, 4],
       [3, 3, 4, 4]])

Here's an alternative. (It still uses A.tolist().)

In [164]: np.swapaxes(A.tolist(), 1, 2).reshape(4, 4)
Out[164]: 
array([[1, 1, 2, 2],
       [1, 1, 2, 2],
       [3, 3, 4, 4],
       [3, 3, 4, 4]])

In the general case, you would need something like:

In [165]: np.swapaxes(A.tolist(), 1, 2).reshape(A.shape[0]*dA, A.shape[1]*dA)
Out[165]: 
array([[1, 1, 2, 2],
       [1, 1, 2, 2],
       [3, 3, 4, 4],
       [3, 3, 4, 4]])
Comments