{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tutorial 5: Introducing NumPy\n",
"Python's built in data types are sufficient for most tasks, but they are not well suited for mathematical computations. The main reason for this is that, out of the box, they do not support vector operations; one cannot easily add corresponding elements in two lists or tuples, for instance. The *NumPy* module provides a new data type called an *array* (amongst others) and optimised mathematical operations. In this tutorial, we will introduce some of the useful functions from the NumPy module, and how these can be used in mathematical operations.\n",
"\n",
"NumPy is an external module -- it is not included in the Python standard library -- and so it has to be installed separately using Python's installer utility *pip*. However, the package should have been installed along with the Jupyter program, so should be available on your system.\n",
"\n",
"To make NumPy available in the current Python session it needs to be imported. This is done using the `import` keyword. Since we will be using the command quite often, we give the imported module a shorted name `np`. The following command will import NumPy as `np` so we can use it in the rest of this tutorial. Note, you will need to use this command every time you wish to use NumPy in a new Python session."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that NumPy is available, we can take a look at the contents of the module. For this we use the `dir` function, which prints a list of all the attributes (functions and properties) that are provided by a given module. NumPy is a large module and provides a large number of functions and types."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(dir(np))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As you can see, there are far too many functions to describe here, but for many uses we need only a few of these functions. If you scan through the above list, you should be able to pick out some common mathematical functions: `sin`; `cos`; `tan`; `sqrt`, `abs`; `exp`; and `log`. These functions are also availaible in the Python standard library `math` module, but these functions have been adapted to accept NumPy's `array` type as input. \n",
"\n",
"NumPy arrays are the heart of NumPy. They provide a vector or matrix type, with the associated operations, that can be used in computations. Let's see how they work."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"arrayA = np.array([1, 2, 3])\n",
"arrayB = np.array([2, 3, 4])\n",
"\n",
"print('arrayA + arrayB:', arrayA + arrayB)\n",
"\n",
"print('2 * arrayA:', 2 * arrayA)\n",
"\n",
"matA = np.array([[1, 2], [3, 4]])\n",
"matB = np.array([[1, 3], [2, 4]])\n",
"\n",
"print('matA * matB: (note that the multiplication is positionwise)', matA * matB, sep='\\n')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that the usual arithmetic operations can be used with array objects for elementwise operations (corresponding elements are added/multiplied). For matrix multiplication, use the `%` operator."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('matA % matB: (matrix multiplication)', matA % matB, sep='\\n')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One of the main use of NumPy arrays is for plotting the graph of a mathematical function. For this purpose, numpy provides the `linspace` function, which creates an array of equally spaced numbers between the first and second arguments. The optional third argument is the number of points to use.\n",
"\n",
"In the following example, we use the matplotlib module to plot a graph. We will cover this module in a later tutorial. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x = np.linspace(-1, 1,100)\n",
"y = np.exp(x)\n",
"from matplotlib.pyplot import plot # Get the plot command from matplotlib.pyplot\n",
"ax = plot(x, y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In addition to the `linspace` function, there are three other utility functions that create standard arrays. For example, the `zeros` and `ones` functions create an array full of zeros or ones. Both accept either an integer or a tuple of integers as arguments which give the size of the array to create. The `eye` function creates an identity matrix array (ones along the diagonal and zeros elsewhere). The input is an integer that gives the size (note that an identity matrix is always n by n)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print('Matrix/vector of zeros', np.zeros(3), sep='\\n') # one dimensional array\n",
"print('Matrix/vector of ones', np.ones((3,2)), sep='\\n') # two dimensional array\n",
"print('Identity matrix 2 by 2', np.eye(2), sep='\\n') # two dimensional array"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises\n",
"1. Create an array that contains the squares of the first 10 integers using the `linspace` function.\n",
"2. Plot the graph of $y = \\log(x)$ for $1\\leq x\\leq 5$. (You will need to use the plot function from above.)\n",
"3. Create a two by two matrix `mat` filled with any numbers. Verify that matrix multiplication by the identity matrix does not change your matrix."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}