import numpy as np
#————————————————-
Indexing in numpy arrays can be confusing for a couple of reasons. The first source of confusion is the sloppy use of terminology, espcially the term ‘dimension’ can mean two subtly different things. In linear algebra the word dimension refers to the number of degrees of freedoms of a vector space, for example the three spacial dimensions. But operators on such space can be described by arrays of numbers which extend in multiple directions, for example a matrix extends in two directions, and its is tempting to also call these directions dimensions. In that sense a matrix is a two dimensional object, and a vector a one dimensional object. But this can lead to ambiguities: Say we have a vector of 3 elements and ask what its dimension is. If we talk about the space in which this vector lives, we answer 3, but if we talk about the array represnentation of the vector, we answer 1. In NumPy the word ‘axis’ is often used for the number of directions in which an array extends.
Next, confusion can arise from previous experience wiht Matlab. In numpy you can have truly one dimensional arrays (i.e. arrays with one axis), whereas in Matlab a vector is actually a two dimenstional array in which one of the dimensions is 1. So in Matlab it makes sense to talk about a column or a row vector, depending on which of the two dimensions is 1. In numpy a one dimensional array is strickly speaking neither a column or a row, and in a computation it can behave like both, depending on the context. Next to that, there is the matter of itterating over the elements, for example if they are to be stored in memory. In the Matlab/Fortran world you start descending down each column, and if you reach the botom of a column you jump to the top of the next column. In the Python/C world you do it the other way around, you run over a row from left to right, and if you reach the end of a row, you move to the next row. And so there are more details which we have to define clearly in order to get rid of all the confusion. What is the definition of a row or a column? And in which order do we index them? etc.
c = np.array([]) # Creates an empty array. It has one dimension in which its size is zero
c = np.array([[]])
Creates an array which contains the empty array. It has two dimensions. We call
the outer array its first dimension, and the inner array its second dimension. The shape of this two dimensional array is (1, 0), which means that it has one element in its first dimension, which is the empty array, and zero elements in its second dimension, i.e. the numer of elements in the empty array.
c = np.array([[[],[]], [[],[]], [[],[]],[[],[]]])
The size of this array is (4, 2, 0) which means we have an outer array which has 4 elements in it. Each of those 4 elements is a array of 2 empty arrays.
So when we have a sequence of indexes, the left-most index is aways in the outer-most array, and so we proceed from outside to inside, so that the last index is into the inner-most array.
#————————————————-
a = np.array([1,2,3]) # Create a vector with 3 elements. A one dimensional array is strictly neither row or column, # but in most cases it behaves like a row. When multiplied with a matrix it behaves like a # column when its places at the right, and as a row when placed at the left.
a = np.array([[1,2,3]]) # Create row vector (1x3 matrix) a = np.array([[1],[2],[3]]) # Create column vector (3x1 matrix) a = np.array([[1,2,3], [10, 20, 30]]) # Create a two dimensional array (2x3 matrix)
a.ndim # Get the number of array dimensions (this is something different than the number of space dimensions) a.shape # Get the number of planes, rows, columns.
a[z, y, x] # indexing order: …, plane, row, colomn.
Note that the documentation does not talk so much about rows and columsn, but axis numbers, like first axis, second axis, etc.
I find it still very confusing what the order of these axis is, and how they relate to rows and columns.
a[0,2] # index row=0, column=2 a[2:5] # indexes [2…5) a[2:] # indexes [2…last]
b = a; # Shallow copy; b becomes a reference to a b = a.copy() # Deep copy; b becomes an independent object
a.T # Returns the transpose
np.linalg.inv(a) # Matrix inverse
a = np.zeros((3,4)) # Create an array of zeros a = np.ones((3,4)) # Create an array of ones a = np.empty((3,4)) # Create an array of uninitialized values
a = np.arange(10, 60, 3) # Create a range [10, 60) with stepsize 3 a = np.linspace(10, 60, 10) # Create a range [10, 60] with 10 steps
b = a + 10 # Add 10 to all array elements b = a * 10 # Multiply all array elements by 10 c = m * a # Elementwise multiplication c = m.dot(a) # Matrix multiplication between m and a c = m @ a # Matrix multiplication between m and a
b = np.sin(a) # Element wise sin() function
v = np.r_[a, b, c, d, …] # Concatinate by adding elements in the direction of the first axis # i.e. the most outer array. In the 2D case this means stacking rows # on top of each other to form longer columns
v = np.c_[a, b, c, d, …] # Concatinate by adding elements in the direction of the last axis, # i.e. the most inner array. In the 2D case this means putting columns # next to each other to form longer rows