Contents

NumPy

NumPy adds arrays and linear albegra to Python, with special functions, transformations, the ability to operate on all elements of an array in one stroke. Remember that in addition to the web resources, in interactive Python try help() for more information on a function:

help("numpy.arange")

will tell you that arange takes one required argument but has several optional ones:

Notice that the array is created with np.zeros(), and the argument is (3,4,5). This means an array of 3x4x5 elements, all zero (float64, by default), grouped as 3 elements, each of 4 elements, each of 5 elements.

An array can be reshaped after it is made. The array stays the same way in memory, but the grouping changes.

myarray = np.array( [1,3,5,7,11,13] )

makes a linear array of 6 elements, and

myarray.reshape(2,3)

changes its shape, so it will be

array([[ 1, 3, 5],
[ 7, 11, 13]])

To create an array of 1000 elements from 0 to 999, the function

my_1d_array = np.arange(1000)

It is reshaped into an array 10x10x10 with

my_3d_array = my_1d_array.reshape((10,10,10))

or an multi-dimensional array may be flattened

my_new_array = my_3d_array.ravel()

The original data remain unchanged, but they are sliced and indexed in different ways depending on the shape of the array and the choices for indexing it.

In summary, NumPy arrays may be created with

np.array()
np.arange()
np.zeros()
np.empty()

reshaped with

myarray.reshape()
myarray.ravel()

written to files in a binary format, and read back with

np.save('myfile.npy', myarray)
newarray = np.load('myfile.npy')

In the following we will see how to index within arrays, operate on arrays, and have arrays functionally combine with one another.

Indexing

Once an array is created, you can refer to it as a whole, or to its elements one-by-one. Create a list, turn it into an array, reshape it, and print it with something like this

NumPy math has the usual trigonometric functions, and others. A full list is in the documentation, and some useful ones are for element-by-element

add(x1,x2)

sub(x1,x2)

multiply(x1,x2)

divide(x1,x2)

power(x1,x2)

square(x)

sqrt(x)

exp(x)

log(x)

log10(x)

absolute(x)

negative(x)

sin(x), cos(x), tan(x)

arcsin(x), arccos(x), arctan(x)

arctan2(x,y) returns the angle whose tangent is the ratio of x and y

sinh(x), cosh(x), tanh(x)

arcsinh(x), arccosh(x), arctanh(x)

degrees(x) or rad2deg(x) convert from radians

radians(x) or deg2rad(x) convert from degrees

rint(x) round to the nearest integer

fix(x) round to the nearest integer toward zero

The broadcast feature of NumPy arrays can be combined with selective indexing in an interesting way. Consider this program to make an array of random numbers in a Gaussian distribution with mean 0, and sigma 1

a = np.random.randn(100)

Print this will show 100 values, some negative, some positive. We can select only those larger than a cutoff, work with them, and put them back in the array

index = a > 0.75
b = a[index]
b= b ** 3 - 100.
a[index] = b

Printing index will show an array of True and False that mask the original array. The array b will only have those elements that satisified the condition used to make the index. The index is used again, to put modified elements back into the original array.

Matrix and vector math in NumPy

We have seen that NumPy has its own set of math functions that broadcast over arrays. If you define an array

a = np.arange(0,1,0.01)*np.pi

you will have an array from 0 to Pi in steps of 0.01*Pi. You can operate on this array, element by element, with np.cos

b = np.cos(a)

and have a new array that contains the cosine of each element of the first one.

Before we move on to SciPy, which builds on NumPy to add a number of useful features, there are two things we should note.

First, NumPy includes matrix math, either by mapping its native arrives to conventional matrices, or by invoking matrix math operations on its arrays. We will only look at this second way, which handles most applications and creates very clear code.

The product of two matrices is done with the "dot" operation between two NumPy arrays.

a = np.array(([1,2],[3,4]))
b = np.array(([0,1],[1,0]))

makes two arrays that may be thought of as 2x2 matrices. To multiply them in the usual sense of matrix multiplication,

c = a.dot(b)

gives

array([[2, 1],
[4, 3]])

and

d = b.dot(a)

gives

array([[3, 4],
[1, 2]])

A matrix inverse is found in the linalg package of NumPy

e = np.linalg.inv(a)

With this we can solve linear equations. Suppose that you have the system of 3 equations in 3 unknowns:

Fourier Transforms in NumPy

NumPy provides Fourier Transforms in several functions, including the one-dimension discrete Fast Fourier Transform or FFT with the function fft(a), and the one-dimensional FFT of real data with rfft(a). It also has n-dimensional Fourier Transforms as well.

As a very simple example, let's consider an exponential decay modulating a sine wave adapted from our dampled cosine plotting example to use NumPy arrays: