ENGI E1006: Introduction to Computing for Engineers and Applied Scientists


Lecture 7: Introduction to Numpy

Reading: Punch and Enbody Appendix C

Midterm Exam

Intro to numpy

To learn about the numpy extension and the entire scipy stack visit scipy.org and numpy.org. The packages provided in the scipy stack are the cornestone of scientific computing in Python. Even though we will only be using numpy and matplotlib you should browse through the core packages in the scipy stack. They will no doubt come in handy further down the road!

numpy arrays

A numpy array is a list-like class designed to facilitate the use of multidimensional arrays for scientific computation in Python. The Python list type has many desireable properties. Chief among them is flexibility. We can grow them, shrink them, store whatever we want in them. All of this comes at a price though. If we are working on something computationally expensive, lists can really slow us down. In the scientific realm we are mainly concerned with arrays of numbers and we don't really need many of the nice flexibility properties that lists have. For this reason, numpy arrays were born. We give up some of the flexibility of lists and in return we get speed.

There are two major concessions we make to use numpy arrays instead of lists:

  1. Length is fixed. We cannot dynamically grow or shrink our arrays.
  2. They should only contain objects of similar type (homogeneous). We will almost exclusively use numeric types when populating numpy arrays.

To use the numpy extension we must first install it and then import it. Fortunately for us, it comes with the Anaconda distribution of Python so it's already intalled. So we just need to import it.

Six ways to make a numpy array:

  1. Create a numpy array from an existing list
  2. Create an array of n zeros.
  3. Create an array of n ones.
  4. Create an array using the numpy function arange
  5. Create an array using the numpy function linspace
  6. Create an array using the numpy function random.rand
In [1]:
import numpy as np
l=[1,2,3]
a=np.array(l)
a
Out[1]:
array([1, 2, 3])

What just happened? We created the numpy array a from the list l.

In [2]:
import numpy as np
a=np.zeros(5)
a
Out[2]:
array([ 0.,  0.,  0.,  0.,  0.])

What just happened? We used the numpy function zeros to create an array of 5 zeros. Notice that the zeros are floating point numbers, not integers. This is the default.

In [3]:
import numpy as np
a=np.ones(5)
a
Out[3]:
array([ 1.,  1.,  1.,  1.,  1.])

What just happened? We used the numpy function ones to create an array of 5 ones. Notice that the ones are floating point numbers, not integers. This is the default.

In [4]:
import numpy as np
a=np.arange(10)
a
Out[4]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

What just happened? We used the numpy function arange to create an array of consecutive integers from 0 to 9. This function is similar to the built-in Python function range.

In [5]:
import numpy as np
a=np.linspace(0,1,11)
a
Out[5]:
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ])

What just happened? We used the numpy function linspace to create an array of 11 floating point numbers evenly spaced betwen the start, 0, and the end, 1.

In [6]:
import numpy as np
a=np.random.rand(10)
a
Out[6]:
array([ 0.8578191 ,  0.42494803,  0.34303195,  0.55554686,  0.83125909,
        0.33536807,  0.08984838,  0.08240393,  0.02741593,  0.27964719])

What just happened? We used the numpy function random.rand to create an array of 10 random floating point numbers chosen uniformly from the half-open interval [0,1).

Four important numpy array properties

  1. dtype - The (numpy) type of the elements contained in the array. Usually numeric, and numpy has its own numeric types similar to the usual Python numerics.
  2. ndim - The number of dimensions the array is organized into
  3. shape - A tuple whose elements are the length of the array in each of its dimensions
  4. size - The total number of elements in the array
    We can explicitly access each of these array attributes. We can explicity change (write) the shape and the dtype. However, don't try to explicitly change the dtype, you probably won't get what you're expecting. We'll see how to do this with a the astype method in a bit.
In [7]:
#construct an array of 12 ones
import numpy as np
a=np.ones(12)

#heck each of the array's properties
print(a.dtype) #depending on your computer this may be float64 or float32
print(a.ndim)
print(a.shape) # since our array is 1 dimensional this will be a tuple with a single element. 
print(a.size)
float64
1
(12,)
12
In [8]:
# explicity change the shape
a.shape=(3,4)
a
Out[8]:
array([[ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.]])

Selecting elements

We can access individual elements of a numpy array using the same array notation we used to access individual elements of a lists. Similarly we can slice numpy arrays in much the same way we learned to slice lists. There are a few convenient extras though when accessing numpy arrays.

In [9]:
import numpy as np
a=np.arange(12) # makes an array with 12 elements. 
a.shape=(3,4) # shapes the array into 3 rows of 4 columns
print(a)
a[0][0]==a[0,0] # True because we can abbreviate the a[0][0] with a[0,0]
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
Out[9]:
True

Because numpy arrays are so often multidimensional we can shortcut the list notation a[i][j] and simply comma separate the individual dimension values inside a single set of brackets like a[i,j].

What if we want to access the entire second row of the array above?

In [10]:
print(a[1,:])
# or we can also just use
print(a[1])
[4 5 6 7]
[4 5 6 7]

I prefer the first approach. It makes it clear that I'm returning more than just a single number.

Two important array methods

  1. astype - this will return a copy of the array converted into the specified type.
  2. reshape - this will return a copy of the array with the newly specified shape.

Note that neither of the above array methods mutate the array they are operating on. They simply return a new array with the specified properties

In [11]:
print('a is:\n',a) # contiuing with a from before
print(a.reshape((4,3))) # return a new array with 4 rows of thre columns
print(a.astype(np.float)) # return a new array with element types converted to numpy floats
print('a is:\n ',a) # and a is unchanged.
a is:
 [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
[[  0.   1.   2.   3.]
 [  4.   5.   6.   7.]
 [  8.   9.  10.  11.]]
a is:
  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]