Removing last 2D array from 3D array - python

I have a three-dimensional numpy array with shape
(5,5,N)
When I add another 5x5 2D array to this 3D array using numpy.dstack the shape changes like
(5,5,N+1)
and so on. I would like to remove the last 2D array I've added to the stack, such that it goes back to having the shape
(5,5,N)
and possibly (5,5,N-1),(5,5,N-2),...,etc.
What is the most pythonic way to achive this?

I would index as follows:
import numpy as np
a = np.ones((5,5,5))
a.shape
(5, 5, 5)
b = np.ones((5, 5, 5))[:, :, :-1]
b.shape
(5, 5, 4)

Related

Append 2d array to 3d array

I have an array of shape (3, 250, 15).
I want to append to it a 2d array of shape (250,15) so that I have a final shape of (4,250,15).
I tried with dstack and np.stack but it does not work.
Can someone give me a suggestion ?
You need to add a dimension (in other words, an axis) to the 2-D array, for example:
import numpy as np
a = np.ones((3, 250, 15))
b = np.ones((250, 15))
c = np.vstack([a, b[None, :, :]])
Now c has shape (4, 250, 15).
If you're not into the None axis trick, you could achieve something similar with np.newaxis or np.reshape.
You can't append a 2D array to a 3D array directly, so you should first expand the axes of the smaller array to become 3D and then append normally. np.expand_dims(b, axis=0) will insert the missing first-axis to array b. Now append the two 3D arrays, np.append(a, b, axis=0).
import numpy as np
a = np.ones((3, 250, 15))
b = np.ones(( 250, 15))
b = np.expand_dims(b, axis=0)
c = np.append(a, b, axis=0)
which works as expected.
print(c.shape)
(4, 250, 15)

How do I reshape a NumPy multi dimensional array to another array with the same dimensions, but different shape?

I have a NumPy multi dimensional array of shape (1,76,76,255). I want to reshape it to another multidimensional array of shape (1,255,76,76). It’s still a 4D array, but I need to change the data indices I guess.
Is there an easy way without using loops?
The function you are looking for is np.moveaxis() which lets you move a source axis to its destination.
>>> arr = np.random.random((1,76,76,255))
>>>
>>> arr.shape
(1, 76, 76, 255)
>>> arr2 = np.moveaxis(arr, 3, 1)
>>> arr2.shape
(1, 255, 76, 76)
>>>
Please note that these axes are 0-indexed

How do we shape Xarray data-array?

I have been working with x-array. How do we reshape the array? Is there any method like re-shape in NumPy?
temp = data['__xarray_dataarray_variable__'][:, :, :]
The above line of code selects all the 3 dimensions of the x-array. Ie the shape of the array is (5, 2, 1).
How do I change the x-array so that it is of the form (5*2, 1).
Thanks in advance.
Xarray syntax is a bit unintuitive. In any case, you can use stack for this:
temp = temp.stack(dim_new=['dim_0','dim_1'])
Assuming originally it was an xarray of shape (dim_0: 5, dim_1: 2, dim_2: 1), temp will then become an xarray with dimensions (dim_2: 1, dim_new: 10). You can further apply temp.transpose('dim_new','dim_2') to get it to (10,1) shape.

How to fuse two axis of a n-dimentional array in Python

Instead of a n-dimentional array, let's take a 3D array to illustrate my question :
>>> import numpy as np
>>> arr = np.ones(24).reshape(2, 3, 4)
So I have an array of shape (2, 3, 4). I would like to concatenate/fuse the 2nd and 3rd axis together to get an array of the shape (2, 12).
Wrongly, thought I could have done it easily with np.concatenate :
>>> np.concatenate(arr, axis=1).shape
(3, 8)
I found a way to do it by a combination of np.rollaxis and np.concatenate but it is increasingly ugly as the array goes up in dimension:
>>> np.rollaxis(np.concatenate(np.rollaxis(arr, 0, 3), axis=0), 0, 2).shape
(2, 12)
Is there any simple way to accomplish this? It seems very trivial, so there must exist some function, but I cannot seem to find it.
EDIT : Indeed I could use np.reshape, which means to compute the dimensions of the axis first. Is it possible without accessing/computing the shape beforehand?
On recent python versions you can do:
anew = a.reshape(*a.shape[:k], -1, *a.shape[k+2:])
I recommend against directly assigning to .shape since it doesn't work on sufficiently noncontiguous arrays.
Let's say that you have n dimensions in your array and that you want to fuse adjacent axis i and i+1:
shape = a.shape
new_shape = list(shape[:i]) + [-1] + list(shape[i+2:])
a.shape = new_shape

filtering a 3D numpy array according to 2D numpy array

I have a 2D numpy array with the shape (3024, 4032).
I have a 3D numpy array with the shape (3024, 4032, 3).
2D numpy array is filled with 0s and 1s.
3D numpy array is filled with values between 0 and 255.
By looking at the 2D array values, I want to change the values in 3D array. If a value in 2D array is 0, I will change the all 3 pixel values in 3D array into 0 along the last axes. If a value in 2D array is 1, I won't change it.
I have checked this question, How to filter a numpy array with another array's values, but it applies for 2 arrays which have same dimensions. In my case, dimensions are different.
How the filtering is applied in two arrays, with same size on 2 dimensions, but not size on the last dimension?
Ok, I'll answer this to highlight one pecularity regarding "missing" dimensions. Lets' assume a.shape==(5,4,3) and b.shape==(5,4)
When indexing, existing dimensions are left aligned which is why #Divakar's solution a[b == 0] = 0 works.
When broadcasting, existing dimensions are right aligned which is why #InvaderZim's a*b does not work. What you need to do is a*b[..., None] which inserts a broadcastable dimension at the right
I think this one is very simple:
If a is a 3D array (a.shape == (5, 4, 3)) filled with values, and b is a 2D array (b.shape == (5, 4)) filled with 1 and 0, then reshape b and multiply them:
a = a * b.reshape(5, 4, 1)
Numpy will automatically expand the arrays as needed.

Categories