convert 2D array into 1D array using np.newaxis - python

I am trying to convert 2D array with one column into 1D vector using np.newaxis. The result I got so far is 3D array instead of 1D vector or 1D array.
The 2D array y1 is:
y1.shape
(506, 1)
y1
array([[0.42 ],
[0.36666667],
[0.66 ],
[0.63333333],
[0.69333333],
... ])
Now I'd like to convert it into 1D array
import numpy as np
y2=y1[np.newaxis,:]
y2.shape
(1, 506, 1)
You can see after using np.newaxis, the shape of y2 become a 3D array, I am expecting the shape of (506,) 1D array.
what is the problem of my above code? Thanks

np.newaxis expand dimension so 2D -> 3D. If you want to reduce your dimension 2D -> 1D, use squeeze:
>>> a
array([[0.42 ],
[0.36666667],
[0.66 ],
[0.63333333],
[0.69333333]])
>>> a.shape()
(5, 1)
>>> a.squeeze()
array([0.42 , 0.36666667, 0.66 , 0.63333333, 0.69333333])
>>> a.squeeze().shape
(5,)
From the documentation:
Each newaxis object in the selection tuple serves to expand the dimensions of the resulting selection by one unit-length dimension. The added dimension is the position of the newaxis object in the selection tuple.

np.newaxis() is used to increase the dimension of the array. It will not decrease the dimension. In order to decrease the dimension, you can use:
reshape()
y1 = np.array(y1).reshape(-1,)
print(y1.shape)
>>> (506,)

Related

Multiply multidimensional numpy array by 1-D array

I have a multidimensional array and a set of scale factors that I want to apply along the first axis:
>>> data.shape, scale_factors.shape
((22, 20, 2048, 2048), (22,))
>>> data * scale_factors
ValueError: operands could not be broadcast together with shapes (22,20,2048,2048) (22,)
I can do this with apply_along_axis, but is there a vectorized way to do this? I found a similar question, but the solution is specific to a 1-D * 2-D operation. The "data" ndarray will not always be the same shape, and won't even always have the same number of dimensions. But the length of the 1-D scale_factors will always be the same as axis 0 of data.
You can try reshape the data into 2D, then broadcast scale_factor to 2D, and reshape back:
(data.reshape(data.shape[0], -1) * scale_factors[:,None]).reshape(data.shape)
Or, you can swap the 0-th axis to the last so you can broadcast:
(data.swapaxes(0,-1) * scale_factors).swapaxes(0,-1)
data * scale_factors.reshape([-1]+[1]*(len(data.shape)-1))
data * scale_factors[:,None,None,None]

How to visualize/connect vectors, matrices and representations in Python and numpy arrays?

I am having trouble visualizing scalars, vectors and matrices as how they are written in a math/physics class to how they would be represented in plain Python and numpy and their corresponding notions of dimensions, axes and shapes.
If I have a scalar, say 5
>>> b = np.array(5)
>>> np.ndim(b)
0
I have 0 dimensions for 5 but what are the axes here? There are functions for ndim and shape but not axes.
For a vector like this:
we say that we have 2 dimensions in physics/math class because it represents a 2D vector but it looks like numpy uses a different notion of this.
Why is it that ndim gives 1 and shape gives what the dimension is?
>>> c = np.array([1,-3])
>>> c
array([ 1, -3])
>>> c.ndim
1
>>> c.shape
(2,)
np.ndim gives 1 then?
I have looked at this tutorial on axes but haven't been able to get how the axes then apply here.
How would you represent the vector above in Python and numpy? Would this be [1, -3] in Python or [[1], [-3]]? How about in numpy? Would it be np.array([1, -3]) or np.array([[1], [-3]])? Which I tend to write, for my eyes' sake, as
np.array([
[1],
[-3]
])
Other than vectors, how would this matrix be represented in both plain Python and numpy? The documentation states that we need to use np.arrays instead.
It is no longer recommended to use this class, even for linear algebra. Instead use regular arrays. The class may be removed in the future.
When it comes to multidimensional arrays, how would I represent/visualize multiple values for all the points in a 3D cube? Say we have a Rubik's cube and each of the sub cubes has a temperature and a color represented with red, green and blue so 4 values for each cube?
A scalar is not an array, so it has 0 dimensions.
np.array([1,-3]) is a 1D array, so c.shape returns a tuple with only one element (2,), just the first dimension and it's telling you there is only 1 dimension and 2 elements in that dimension.
You are correct np.array([[1], [-3]]) is the vector you have in 2. c.shape gives (2,1) meaning there are 2 rows and 1 column. c.ndim gives 2 since there are 2 dimensions x and y. It's a 2D/planar array
For 3., you would create it as np.array([[1,2,3], [4,5,6], [7,8,9]]). shape returns (3,3) meaning 3 rows and 3 columns. ndim returns 2 because it's still a 2D/planar array.
A ndarray has a shape, a tuple. ndim is the length of that tuple, and may be 0. The array has ndim axes (sometimes called dimensions).
np.array(5)
has shape (), 0 ndim and no axes.
np.array([1,2,3,4])
has (4,) shape, and 1 axis. It can be reshaped to (4,1), or (1,4) or (2,2) or even (2,1,2) or (1,4,1).
Your A can be created with
A = np.arange(1,10).reshape(3,3)
That's a 9 element 1d array reshaped to (3,3)
numpy arrays have a print display, with [] marking dimensional nesting. A.tolist() produces a list with 3 elements, each a 3 element list.
Rows, columns, planes are useful ways of talking about arrays, but are not a formal part of their definition.

How to reshape a 1d array to a 3d array with diffrerent size of 2d arrays?

I want to reshape this array: np.array(np.arange(15)) to a 3d array that is built from a 3x3 array and a 3x2 array.
I've tried to do it with the reshape method but it didn't work.
I thought that maybe reshape can get a number of tuples maybe.
a=np.array(np.arange(15)).reshape(1,((3,2),(3,3)))
but I then I saw it cant.
How can I reshape it then? is there a nice way?
a multidimensional array can't have dimensions with different size.
but if you want a tuple you will need to split the array in 2 parts, the first that match in size with the 3x3 array and the second that match the 3x2, at this point you'll have 2 one dimensional array, then reshape them
arr1 = arr1.reshape((3,3))
arr2 = arr2.reshape((3,2))
tuple = arr1, arr2

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.

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.

Categories