Axis interpretation in 3D Numpy arrays - python

I am using the following example to understand the working of axis in 3D arrays in Numpy.
a = np.array([[9],[9],[8]])
b = np.array([[1],[4],[6]])
print(np.stack([a,b],axis=0)
>>>
array([[[9],
[9],
[8]],
[[1],
[4],
[6]]])
print(np.stack([a,b],axis=1)
>>>
array([[[9],
[1]],
[[9],
[4]],
[[8],
[6]]])
print(np.stack([a,b],axis=2)
>>>
array([[[9, 1]],
[[9, 4]],
[[8, 6]]])
I am able to understand how axis=0 and axis=1 work. Can anyone explain how axis=2 works with pictorial representation as it is done for 2D arrays?
For reference
print(np.stack([a,b],axis=0.shape) #(2,3,1)
print(np.stack([a,b],axis=1.shape) #(3,2,1)
print(np.stack([a,b],axis=2.shape) #(3,1,2)

You can see 3D numpy arrays as data cube.
Let's suppose we have an np.array A.
(z, y, x) = np.shape(A). You notice that the z dimensions corresponds to the indices 0.
Your array A is simply z 2d array of dimensions (y, x) that you stack together.
It explains why A[0,:,:] is a 2d array.
Axis = 2 simply points out that you consider 2d arrays stacked on the z direction!

Related

Python Numpy Transpose Matrix [duplicate]

I use Python and NumPy and have some problems with "transpose":
import numpy as np
a = np.array([5,4])
print(a)
print(a.T)
Invoking a.T is not transposing the array. If a is for example [[],[]] then it transposes correctly, but I need the transpose of [...,...,...].
It's working exactly as it's supposed to. The transpose of a 1D array is still a 1D array! (If you're used to matlab, it fundamentally doesn't have a concept of a 1D array. Matlab's "1D" arrays are 2D.)
If you want to turn your 1D vector into a 2D array and then transpose it, just slice it with np.newaxis (or None, they're the same, newaxis is just more readable).
import numpy as np
a = np.array([5,4])[np.newaxis]
print(a)
print(a.T)
Generally speaking though, you don't ever need to worry about this. Adding the extra dimension is usually not what you want, if you're just doing it out of habit. Numpy will automatically broadcast a 1D array when doing various calculations. There's usually no need to distinguish between a row vector and a column vector (neither of which are vectors. They're both 2D!) when you just want a vector.
Use two bracket pairs instead of one. This creates a 2D array, which can be transposed, unlike the 1D array you create if you use one bracket pair.
import numpy as np
a = np.array([[5, 4]])
a.T
More thorough example:
>>> a = [3,6,9]
>>> b = np.array(a)
>>> b.T
array([3, 6, 9]) #Here it didn't transpose because 'a' is 1 dimensional
>>> b = np.array([a])
>>> b.T
array([[3], #Here it did transpose because a is 2 dimensional
[6],
[9]])
Use numpy's shape method to see what is going on here:
>>> b = np.array([10,20,30])
>>> b.shape
(3,)
>>> b = np.array([[10,20,30]])
>>> b.shape
(1, 3)
For 1D arrays:
a = np.array([1, 2, 3, 4])
a = a.reshape((-1, 1)) # <--- THIS IS IT
print a
array([[1],
[2],
[3],
[4]])
Once you understand that -1 here means "as many rows as needed", I find this to be the most readable way of "transposing" an array. If your array is of higher dimensionality simply use a.T.
You can convert an existing vector into a matrix by wrapping it in an extra set of square brackets...
from numpy import *
v=array([5,4]) ## create a numpy vector
array([v]).T ## transpose a vector into a matrix
numpy also has a matrix class (see array vs. matrix)...
matrix(v).T ## transpose a vector into a matrix
numpy 1D array --> column/row matrix:
>>> a=np.array([1,2,4])
>>> a[:, None] # col
array([[1],
[2],
[4]])
>>> a[None, :] # row, or faster `a[None]`
array([[1, 2, 4]])
And as #joe-kington said, you can replace None with np.newaxis for readability.
To 'transpose' a 1d array to a 2d column, you can use numpy.vstack:
>>> numpy.vstack(numpy.array([1,2,3]))
array([[1],
[2],
[3]])
It also works for vanilla lists:
>>> numpy.vstack([1,2,3])
array([[1],
[2],
[3]])
instead use arr[:,None] to create column vector
You can only transpose a 2D array. You can use numpy.matrix to create a 2D array. This is three years late, but I am just adding to the possible set of solutions:
import numpy as np
m = np.matrix([2, 3])
m.T
Basically what the transpose function does is to swap the shape and strides of the array:
>>> a = np.ones((1,2,3))
>>> a.shape
(1, 2, 3)
>>> a.T.shape
(3, 2, 1)
>>> a.strides
(48, 24, 8)
>>> a.T.strides
(8, 24, 48)
In case of 1D numpy array (rank-1 array) the shape and strides are 1-element tuples and cannot be swapped, and the transpose of such an 1D array returns it unchanged. Instead, you can transpose a "row-vector" (numpy array of shape (1, n)) into a "column-vector" (numpy array of shape (n, 1)). To achieve this you have to first convert your 1D numpy array into row-vector and then swap the shape and strides (transpose it). Below is a function that does it:
from numpy.lib.stride_tricks import as_strided
def transpose(a):
a = np.atleast_2d(a)
return as_strided(a, shape=a.shape[::-1], strides=a.strides[::-1])
Example:
>>> a = np.arange(3)
>>> a
array([0, 1, 2])
>>> transpose(a)
array([[0],
[1],
[2]])
>>> a = np.arange(1, 7).reshape(2,3)
>>> a
array([[1, 2, 3],
[4, 5, 6]])
>>> transpose(a)
array([[1, 4],
[2, 5],
[3, 6]])
Of course you don't have to do it this way since you have a 1D array and you can directly reshape it into (n, 1) array by a.reshape((-1, 1)) or a[:, None]. I just wanted to demonstrate how transposing an array works.
Another solution.... :-)
import numpy as np
a = [1,2,4]
[1, 2, 4]
b = np.array([a]).T
array([[1],
[2],
[4]])
The name of the function in numpy is column_stack.
>>>a=np.array([5,4])
>>>np.column_stack(a)
array([[5, 4]])
I am just consolidating the above post, hope it will help others to save some time:
The below array has (2, )dimension, it's a 1-D array,
b_new = np.array([2j, 3j])
There are two ways to transpose a 1-D array:
slice it with "np.newaxis" or none.!
print(b_new[np.newaxis].T.shape)
print(b_new[None].T.shape)
other way of writing, the above without T operation.!
print(b_new[:, np.newaxis].shape)
print(b_new[:, None].shape)
Wrapping [ ] or using np.matrix, means adding a new dimension.!
print(np.array([b_new]).T.shape)
print(np.matrix(b_new).T.shape)
There is a method not described in the answers but described in the documentation for the numpy.ndarray.transpose method:
For a 1-D array this has no effect, as a transposed vector is simply the same vector. To convert a 1-D array into a 2D column vector, an additional dimension must be added. np.atleast2d(a).T achieves this, as does a[:, np.newaxis].
One can do:
import numpy as np
a = np.array([5,4])
print(a)
print(np.atleast_2d(a).T)
Which (imo) is nicer than using newaxis.
As some of the comments above mentioned, the transpose of 1D arrays are 1D arrays, so one way to transpose a 1D array would be to convert the array to a matrix like so:
np.transpose(a.reshape(len(a), 1))
To transpose a 1-D array (flat array) as you have in your example, you can use the np.expand_dims() function:
>>> a = np.expand_dims(np.array([5, 4]), axis=1)
array([[5],
[4]])
np.expand_dims() will add a dimension to the chosen axis. In this case, we use axis=1, which adds a column dimension, effectively transposing your original flat array.

Dot product with numpy gives array with size (n, )

I am trying to get the dotproduct of two arrays in python using the numpy package. I get as output an array of size (n,). It says that my array has no column while I do see the results when I print it. Why does my array have no column and how do I fix this?
My goal is to calculate y - np.dot(x,b). The issue is that y is (124, 1) while np.dot(x,b) is (124,)
Thanks
It seems that you are trying to subtract two arrays of a different shape. Fortunately, it is off by a single additional axis, so there are two ways of handling it.
(1) You slice the y array to match the shape of the dot(x,b) array:
y = y[:,0]
print(y-np.dot(x,b))
(2) You add an additional axis on the np.dot(x,b) array:
dot = np.dot(x,b)
dot = dot[:,None]
print(y-dot)
Hope this helps
it may depends on the dimension of your array
For example :
a = [1, 0]
b = [[4, 1], [2, 2]]
c = np.dot(a,b)
gives
array([4, 1])
and its shape is (2,)
but if you change a like :
a = [[1, 0],[1,1]]
then result is :
array([[4, 1],
[6, 3]])
and its shape is (2,2)

Flipping numpy array axes based on values in second array

Currently writing a custom data generator for Keras and I'm looking to randomly flip a numpy input array during training for data augmentation purposes.
X: input array of shape (batchsize, y_dim, x_dim)
to_flip: boolean array of shape (batchsize, X_rank) that describes which axes to flip
For example:
X = [[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]]
to_flip = [[0, 1],
[1, 0]]
flipped_X = [[[1, 0],
[3, 2]],
[[6, 7],
[4, 5]]]
or any combination of axes (both/no axes flipped).
I couldn't figure out how to use either np.flip or advanced indexing (e.g. X[::-1]) by themselves to get this effect. Ideally, I'd be able to find a solution that could be applied to the whole batch without explicit loops, because I believe that such a solution would be faster.
The best solution I have currently is:
def flip_axes(an_input, axes_to_flip):
axis_inds_to_flip = np.where(axes_to_flip.reshape(-1))[0]
return np.flip(an_input, axis_inds_to_flip)[None, ...]
flipped_X = np.concatenate([flip_axes(an_input, axes_to_flip)
for an_input, axes_to_flip
in zip(X, to_flip)], axis=0)
Anyone have any thoughts? Would this indeed be quicker than what I've written here?
edit: I've revised my solution so that it executes and I've added my motivation for the question.
You can do it using python indexing as follows,
flipped_X = []
for sample, flip in zip(X, to_flip):
flipped = [*sample] # Generate a copy of x
if flip[0]: # if flip[0] is 1
flipped = flipped[::-1] # Flip matrix vertically
if flip[1]: # if flip[1] is 1
flipped = [elem[::-1] for elem in flipped] # Flip elements to flip horizontally
flipped_X.append(flipX) # Finally append to result
print(flipped_X)
Will output:
[[[1, 0], [3, 2]], [[6, 7], [4, 5]]]
EDIT: Using numpy you can achieve the same result with np.flip(m, axis), where m will be each matrix in X and axis will be a tuple of the indexes to flip. For example:
to_flip = [[0,0], [1,0], [0,1], [1,1]]
so the indexes will be
[[], [0], [1], [0,1]]
# Get indexes to flip at each sample
flip_idxes = map(lambda flip: [idx for idx, x in enumerate(flip) if x], to_flip)
# Flip samples
flipped_X = np.array([np.flip(sample, indexes) for sample, indexes in zip(X, flip_idxes)])

what's the difference between np.array[:,0] and np.array[:,[0]]?

I have a numpy array cols2:
print(type(cols2))
print(cols2.shape)
<class 'numpy.ndarray'>
(97, 2)
I was trying to get the first column of this 2d numpy array using the first code below, then i got a vector instead of my ideal one column of data. the second code seem to get me the ideal answer, but i am confused what does the second code is doing by adding a bracket outside the zero?
print(type(cols2[:,0]))
print(cols2[:,0].shape)
<class 'numpy.ndarray'>
(97,)
print(type(cols2[:,[0]]))
print(cols2[:,[0]].shape)
<class 'numpy.ndarray'>
(97, 1)
cols2[:, 0] specifies that you want to slice out a 1D vector of length 97 from a 2D array. cols2[:, [0]] specifies that you want to slice out a 2D sub-array of shape (97, 1) from the 2D array. The square brackets [] make all the difference here.
v = np.arange(6).reshape(-1, 2)
v[:, 0]
array([0, 2, 4])
v[:, [0]]
array([[0],
[2],
[4]])
The fundamental difference is the extra dimension in the latter command (as you've noted). This is intended behaviour, as implemented in numpy.ndarray.__get/setitem__ and codified in the NumPy documentation.
You can also specify cols2[:,0:1] to the same effect - a column sub-slice.
v[:, 0:1]
array([[0],
[2],
[4]])
For more information, look at the notes on Advanced Indexing in the NumPy docs.
The extra square brackets around 0 in cols2[:, [0]] adds an extra dimension.
This becomes more clear when you print the results of your code:
A = np.array([[1, 2],
[3, 4],
[5, 6]])
A.shape # (3, 2)
A[:, 0].shape # (3,)
A[:, 0] # array([1, 3, 5])
A[:, [0]]
# array([[1],
# [3],
# [5]])
An n-D numpy array can only use n integers to represent its shape. Therefore, a 1D array is represented by only a single integer. There is no concept of "rows" or "columns" of a 1D array.
You should resist the urge to think of numpy arrays as having rows and columns, but instead consider them as having dimensions and shape. This is a fundamental difference between numpy.array and numpy.matrix. In almost all cases, numpy.array is sufficient.

Shortest Syntax To Use numpy 1d-array As sklearn X

I often have two numpy 1d arrays, x and y, and would like to perform some quick sklearn fitting + prediction using them.
import numpy as np
from sklearn import linear_model
# This is an example for the 1d aspect - it's obtained from something else.
x = np.array([1, 3, 2, ...])
y = np.array([12, 32, 4, ...])
Now I'd like to do something like
linear_model.LinearRegression().fit(x, y)...
The problem is that it expects an X which is a 2d column array. For this reason, I usually feed it
x.reshape((len(x), 1))
which I find cumbersome and hard to read.
Is there some shorter way to transform a 1d array to a 2d column array (or, alternatively, get sklearn to accept 1d arrays)?
You can slice your array, creating a newaxis:
x[:, None]
This:
>>> x = np.arange(5)
>>> x[:, None]
array([[0],
[1],
[2],
[3],
[4]])
Is equivalent to:
>>> x.reshape(len(x), 1)
array([[0],
[1],
[2],
[3],
[4]])
If you find it more readable, you can use a transposed matrix:
np.matrix(x).T
If you want an array:
np.matrix(x).T.A

Categories

Resources