Generalizing matrix transpose in numpy - python

Let a be a list in python.
a = [1,2,3]
When matrix transpose is applied to a, we get:
np.matrix(a).transpose()
matrix([[1],
[2],
[3]])
I am looking to generalize this functionality and will next illustrate what I am looking to do with the help of an example. Let b be another list.
b = [[1, 2], [2, 3], [3, 4]]
In a, the list items are 1, 2, and 3. I would like to consider each of [1,2], [2,3], and [3,4] as list items in b, only for the purpose of performing a transpose. I would like the output to be as follows:
array([[[1,2]],
[[2,3]],
[[3,4]]])
In general, I would like to be able to specify what a list item would look like, and perform a matrix transpose based on that.
I could just write a few lines of code to do the above, but my purpose of asking this question is to find out if there is an inbuilt numpy functionality or a pythonic way, to do this.
EDIT: unutbu's output below matches the output that I have above. However, I wanted a solution that would work for a more general case. I have posted another input/output below. My initial example wasn't descriptive enough to convey what I wanted to say. Let items in b be [1,2], [2,3], [3,4], and [5,6]. Then the output given below would be of doing a matrix transpose on higher dimension elements. More generally, once I describe what an 'item' would look like, I would like to know if there is a way to do something like a transpose.
Input: b = [[[1, 2], [2, 3]], [[3, 4], [5,6]]]
Output: array([[[1,2], [3,4]],
[[2,3], [5,6]]])

Your desired array has shape (3,1,2). b has shape (3,2). To stick an extra axis in the middle, use b[:,None,:], or (equivalently) b[:, np.newaxis, :]. Look for "newaxis" in the section on Basic Slicing.
In [178]: b = np.array([[1, 2], [2, 3], [3, 4]])
In [179]: b
Out[179]:
array([[1, 2],
[2, 3],
[3, 4]])
In [202]: b[:,None,:]
Out[202]:
array([[[1, 2]],
[[2, 3]],
[[3, 4]]])
Another userful tool is np.swapaxes:
In [222]: b = np.array([[[1, 2], [2, 3]], [[3, 4], [5,6]]])
In [223]: b.swapaxes(0,1)
Out[223]:
array([[[1, 2],
[3, 4]],
[[2, 3],
[5, 6]]])
The transpose, b.T is the same as swapping the first and last axes, b.swapaxes(0,-1):
In [226]: b.T
Out[226]:
array([[[1, 3],
[2, 5]],
[[2, 4],
[3, 6]]])
In [227]: b.swapaxes(0,-1)
Out[227]:
array([[[1, 3],
[2, 5]],
[[2, 4],
[3, 6]]])
Summary:
Use np.newaxis (or None) to add new axes. (Thus, increasing the dimension of the array)
Use np.swapaxes to swap any two axes.
Use np.transpose to permute all the axes at once. (Thanks to #jorgeca for pointing this out.)
Use np.rollaxis to "rotate" the axes.

Related

Stack several 2D arrays to produce a 3D array

I have 4 numpy arrays, each of shape (5,5). I would like to stack them such that I get a new array of shape (5,5,4). I tried using:
N = np.stack((a, b, c, d))
but, as I am new to using numpy, I cannot understand why that is giving a shape of (4, 5, 5) instead of (5, 5, 4). Is there another method I should be using? dstack works but changes my arrays, I think it transposes them.
For example, 4 arrays
[[1,2]
[3,4]]
[[1,2]
[3,4]]
[[1,2]
[3,4]]
[[1,2]
[3,4]]
when stacked I am expecting:
[[[1,2]
[3,4]]
[[1,2]
[3,4]]
[[1,2]
[3,4]]
[[1,2]
[3,4]]]
This is working as expected with stack but would give a shape of (4,2,2) instead of (2,2,4). From my understanding, shape is (rows, columns, depth) Am I wrong in this?
I believe you could concatenate the arrays, and reshape into a 3D array as:
l = [a,b,c,d]
np.concatenate(l).reshape(len(l), *a.shape)
Or if you want to avoid creating that list and know the amount of arrays beforehand:
np.concatenate((a,b,c,d)).reshape(4, *a.shape)
Checking on the shared example:
a = [[1, 2], [3, 4]]
d = c = b = a
np.concatenate((a,b,c,d)).reshape(4, *np.array(a).shape)
array([[[1, 2],
[3, 4]],
[[1, 2],
[3, 4]],
[[1, 2],
[3, 4]],
[[1, 2],
[3, 4]]])
In [10]: arr = np.arange(1,5).reshape(2,2)
In [11]: np.stack((arr,arr,arr))
Out[11]:
array([[[1, 2],
[3, 4]],
[[1, 2],
[3, 4]],
[[1, 2],
[3, 4]]])
In [12]: _.shape
Out[12]: (3, 2, 2)
Default stack joins the arrays on a new first axis, the same as np.array((arr,arr,arr)).shape
If given an axis parameter it can join them as:
In [13]: np.stack((arr,arr,arr), axis=2)
Out[13]:
array([[[1, 1, 1],
[2, 2, 2]],
[[3, 3, 3],
[4, 4, 4]]])
In [14]: _.shape
Out[14]: (2, 2, 3)
np.dstack does the same thing, where d stands for 'depth`'.
The last dimension (here 3) is displayed as the innermost columns.
Selecting one 'channel' produces a 2d array:
In [17]: np.stack((arr,arr,arr), axis=2)[:,:,0]
Out[17]:
array([[1, 2],
[3, 4]])
For 3 dimensions, the first dimension is blocks or planes, and the middle rows. Those names are conveniences, helping us visualize the action, but don't have inherent means in numpy. For images the last dimension often is called colors or channels, and has size 3 or 4. A 4d array of images could described as
(batches, height, width, color)
But the actual meanings depend on how you are processing the array.

How to reshape numpy array with reorder?

I have a 1 x 2 x 3 array:
>>> a = np.array([[[1,2,3],[4,5,6]]])
>>> a
array([[[1, 2, 3],
[4, 5, 6]]])
>>> a.shape
(1, 2, 3)
I want to reshape it to (3,1,2), but so that the elements along original dim 3 are now along dim 1. I want the result to look like this:
>>> new_a
array([[[1, 4]],
[[2, 5]],
[[3, 6]]])
and when I just use reshape, I get the the right shape, but the elements are in the same order, not what I want:
>>> a.reshape((3,1,2))
array([[[1, 2]],
[[3, 4]],
[[5, 6]]])
How can I achieve this?
Simply use np.transpose -
a.transpose(2,0,1)
Sample run -
In [347]: a
Out[347]:
array([[[1, 2, 3],
[4, 5, 6]]])
In [348]: a.transpose(2,0,1)
Out[348]:
array([[[1, 4]],
[[2, 5]],
[[3, 6]]])
Alternatively :
With np.moveaxis -
np.moveaxis(a,2,0)
With np.rollaxis -
np.rollaxis(a,2,0)
There are a few ways, but transpose() is probably the easiest:
array.transpose(2,0,1)
import einops
einops.rearrange(x, 'x y z -> z x y')
And better use some meaningful axes names instead of x, y, z (like width, height, etc.)

Numpy merge two arrays can i make a numpy array like this?

I am trying two array like this. It's different from column_stack so I am not able to find how to do it from documentation or google search.
I have arrays a and b. How can I make c from them ?
a = [[1, 2],[3, 4]]
b = [[5 , 6]]
c = [[[1, 2],[5]],
[3, 4],[6]]]
I need this to input the values to theanets.
In [54]:
a = np.array([[1, 2],[3, 4]])
a
Out[54]:
array([[1, 2],
[3, 4]])
In [55]:
b = np.array([[5 , 6]])
b
Out[55]:
array([[5, 6]])
In [96]:
c = [[a[n].tolist() , b[:,n].tolist()] for n in range(len(a))]
c
Out[96]:
[[[1, 2], [5]], [[3, 4], [6]]]

Combining an array using Python and NumPy

I have two arrays of the form:
a = np.array([1,2,3])
b = np.array([4,5,6])
Is there a NumPy function which I can apply to these arrays to get the followng output?
[[1,4],[2,5][3,6]]
np.vstack((a,b)).T
returns
array([[1, 4],
[2, 5],
[3, 6]])
and
np.vstack((a,b)).T.tolist()
returns exactly what you need:
[[1, 4], [2, 5], [3, 6]]

How to delete column in 3d numpy array

I have a numpy array that looks like this
[
[[1,2,3], [4,5,6]],
[[3,8,9], [2,9,4]],
[[7,1,3], [1,3,6]]
]
I want it like this after deleting first column
[
[[2,3], [5,6]],
[[8,9], [9,4]],
[[1,3], [3,6]]
]
so currently the dimension is 3*3*3, after removing the first column it should be 3*3*2
You can slice it as so, where 1: signifies that you only want the second and all remaining columns from the inner most array (i.e. you 'delete' its first column).
>>> a[:, :, 1:]
array([[[2, 3],
[5, 6]],
[[8, 9],
[9, 4]],
[[1, 3],
[3, 6]]])
Since you are using numpy I'll mention numpy way of doing this. First of all, the dimension you have specified for the question seems wrong. See below
x = np.array([
[[1,2,3], [4,5,6]],
[[3,8,9], [2,9,4]],
[[7,1,3], [1,3,6]]
])
The shape of x is
x.shape
(3, 2, 3)
You can use numpy.delete to remove a column as shown below
a = np.delete(x, 0, 2)
a
array([[[2, 3],
[5, 6]],
[[8, 9],
[9, 4]],
[[1, 3],
[3, 6]]])
To find the shape of a
a.shape
(3, 2, 2)

Categories