How do we shape Xarray data-array? - python

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.

Related

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

Insert A numpy multi dimensional array inside another 1d array

I already have an array with shape (1, 224, 224), a single channel image. I want to change that to (1, 1, 224, 224). I have been trying
newarr.shape
#(1,224,224)
arr = np.array([])
np.append(arr, newarr, 1)
I always get this
IndexError: axis 1 out of bounds [0, 1). If i remove the axis as 0 , then the array gets flattened . What am I doing wrong ?
A dimension of 1 is arbitrary, so it sounds like you want to simply reshape the array. This can accomplished by:
newarr.shape = (1, 1, 244, 244)
or
newarr = newarr[None]
The only way to do an insert into a higher dimensional array is
bigger_arr = np.zeros((1, 1, 224, 224))
bigger_arr[0,...] = arr
In other words, make a target array of the right size, and assign values.
np.append is a booby trap. Avoid it.
Occasionally that's a useful way of thinking of this. But it's simpler, and quicker, to think of this as a reshape problem.
bigger_arr = arr.reshape(1,1,224,224)
bigger_arr = arr[np.newaxis,...]
arr.shape = (1,1,224,224) # a picky inplace change
bigger_arr = np.expand_dims(arr, 0)
This last one does
a.reshape(shape[:axis] + (1,) + a.shape[axis:])
which gives an idea of how to deal with dimensions programmatically.

Removing last 2D array from 3D array

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)

How to get these shapes to line up for a numpy matrix

I'm trying to input vectors into a numpy matrix by doing:
eigvec[:,i] = null
However I keep getting the error:
ValueError: could not broadcast input array from shape (20,1) into shape (20)
I've tried using flatten and reshape, but nothing seems to work
The shapes in the error message are a good clue.
In [161]: x = np.zeros((10,10))
In [162]: x[:,1] = np.ones((1,10)) # or x[:,1] = np.ones(10)
In [163]: x[:,1] = np.ones((10,1))
...
ValueError: could not broadcast input array from shape (10,1) into shape (10)
In [166]: x[:,1].shape
Out[166]: (10,)
In [167]: x[:,[1]].shape
Out[167]: (10, 1)
In [168]: x[:,[1]] = np.ones((10,1))
When the shape of the destination matches the shape of the new value, the copy works. It also works in some cases where the new value can be 'broadcasted' to fit. But it does not try more general reshaping. Also note that indexing with a scalar reduces the dimension.
I can guess that
eigvec[:,i] = null.flat
would work (however, null.flatten() should work too). In fact, it looks like NumPy complains because of you are assigning a pseudo-1D array (shape (20, 1)) to a 1D array which is considered to be oriented differently (shape (1, 20), if you wish).
Another solution would be:
eigvec[:,i] = null.T
where you properly transpose the "vector" null.
The fundamental point here is that NumPy has "broadcasting" rules for converting between arrays with different numbers of dimensions. In the case of conversions between 2D and 1D, a 1D array of size n is broadcast into a 2D array of shape (1, n) (and not (n, 1)). More generally, missing dimensions are added to the left of the original dimensions.
The observed error message basically said that shapes (20,) and (20, 1) are not compatible: this is because (20,) becomes (1, 20) (and not (20, 1)). In fact, one is a column matrix, while the other is a row matrix.

3D tiling of a numpy array

Provided a 1D array as a:
a=np.arange(8)
I would like it to be reproduced in a 3D scheme in order to have such shape (n1, len(a), n3).
Is there any working way to obtain this via np.tile? It seems trivial, but trying:
np.shape( np.tile(a, (n1,1,n3)) )
or
np.shape( np.tile( np.tile(a, (n1,1)), (1,1,n2) ) )
I never obtain what I need, being the resulting shapes (n1, 1, len(a)*n3) or (1, n1, len(a)*n3).
Maybe it is me not understanding how tile works ...
What's happening is that a is being made a 1x1x8 array before the tiling is applied. You'll need to make a a 1x8x1 array and then call tile.
As the documentation for tile notes:
If A.ndim < d, A is promoted to be d-dimensional by prepending
new axes. So a shape (3,) array is promoted to (1, 3) for 2-D
replication, or shape (1, 1, 3) for 3-D replication. If this is not
the desired behavior, promote A to d-dimensions manually before
calling this function.
The easiest way to get the result you're after is to slice a with None (or equivalently, np.newaxis) to make it the correct shape.
As a quick example:
import numpy as np
a = np.arange(8)
result = np.tile(a[None, :, None], (4, 1, 5))
print result.shape

Categories