1355 lines
91 KiB
Text
1355 lines
91 KiB
Text
|
{
|
||
|
"cells": [
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_mb.png\">](https://mybinder.org/v2/gh/webartifex/intro-to-data-science/main?urlpath=lab/tree/01_scientific_stack/00_content_numpy.ipynb)."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"# Chapter 1: Python's Scientific Stack (Part 1)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Python itself does not come with any scientific algorithms. However, over time, many third-party libraries emerged that are useful to build machine learning applications. In this context, \"third-party\" means that the libraries are *not* part of Python's standard library.\n",
|
||
|
"\n",
|
||
|
"Among the popular ones are [numpy <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/) (numerical computations, linear algebra), [pandas <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_pd.png\">](https://pandas.pydata.org/) (data processing), [matplotlib <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_plt.png\">](https://matplotlib.org/) (visualisations), and [scikit-learn <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_skl.png\">](https://scikit-learn.org/stable/index.html) (machine learning algorithms)."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"## Extending Python with Third-party Packages"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Before we can import these libraries, we must ensure that they installed on our computers. If you installed Python via the Anaconda Distribution that should already be the case. Otherwise, we can use Python's **package manager** `pip` to install them manually.\n",
|
||
|
"\n",
|
||
|
"`pip` is a so-called command-line interface (CLI), meaning it is a program that is run within a terminal window. JupyterLab allows us to run such a CLI tool from within a notebook by starting a code cell with a single `%` symbol. Here, this does not mean Python's modulo operator but is just an instruction to JupyterLab that the following code is *not* Python.\n",
|
||
|
"\n",
|
||
|
"So, let's proceed by installing [numpy <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/) and [matplotlib <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_plt.png\">](https://matplotlib.org/)."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 1,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"name": "stdout",
|
||
|
"output_type": "stream",
|
||
|
"text": [
|
||
|
"Requirement already satisfied: numpy in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (1.21.1)\n",
|
||
|
"Note: you may need to restart the kernel to use updated packages.\n"
|
||
|
]
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"%pip install numpy"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 2,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"name": "stdout",
|
||
|
"output_type": "stream",
|
||
|
"text": [
|
||
|
"Requirement already satisfied: matplotlib in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (3.4.3)\n",
|
||
|
"Requirement already satisfied: python-dateutil>=2.7 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (2.8.2)\n",
|
||
|
"Requirement already satisfied: cycler>=0.10 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (0.10.0)\n",
|
||
|
"Requirement already satisfied: pyparsing>=2.2.1 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (2.4.7)\n",
|
||
|
"Requirement already satisfied: kiwisolver>=1.0.1 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (1.3.2)\n",
|
||
|
"Requirement already satisfied: pillow>=6.2.0 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (8.3.2)\n",
|
||
|
"Requirement already satisfied: numpy>=1.16 in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from matplotlib) (1.21.1)\n",
|
||
|
"Requirement already satisfied: six in /home/webartifex/repos/intro-to-data-science/.venv/lib/python3.8/site-packages (from cycler>=0.10->matplotlib) (1.16.0)\n",
|
||
|
"Note: you may need to restart the kernel to use updated packages.\n"
|
||
|
]
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"%pip install matplotlib"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"After we have ensured that the third-party libraries are installed locally, we can simply go ahead with the `import` statement. All the libraries are commonly imported with shorter prefixes for convenient use later on."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 3,
|
||
|
"metadata": {},
|
||
|
"outputs": [],
|
||
|
"source": [
|
||
|
"import numpy as np\n",
|
||
|
"import matplotlib.pyplot as plt"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Let's see how the data type provided by these scientific libraries differ from Python's built-in ones."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"## Vectors and Matrices with Numpy"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"As an example, let's start by creating a `list` object."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 4,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"[1, 2, 3, 4, 5]"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 4,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"vector = [1, 2, 3, 4, 5]\n",
|
||
|
"\n",
|
||
|
"vector"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"We call the `list` object by the name `vector` as that is what the data is supposed to mean conceptually. As we remember from our linear algebra courses, vectors should implement scalar-multiplication. So, the following code cell should result in `[3, 6, 9, 12, 15]` as the answer. Surprisingly, the result is a new `list` with all the elements in `vector` repeated three times. That operation is called **concatenation** and is an example of a concept called **operator overloading**. That means that an operator, like `*` in the example, may exhibit a different behavior depending on the data type of its operands."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 5,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 5,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"3 * vector"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"[numpy <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/), among others, provides a data type called an **n-dimensional array**. This may sound fancy at first but when used with only 1 or 2 dimensions, it basically represents vectors and matrices as we know them from linear algebra. Additionally, arrays allow for much faster computations as they are implemented in the very efficient [C language <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_wiki.png\">](https://en.wikipedia.org/wiki/C_%28programming_language%29) and optimized for numerical operations."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"To create an array, we use the [np.array() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html#numpy-array) constructor and provide it a `list` of values."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 6,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([1, 2, 3, 4, 5])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 6,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1 = np.array([1, 2, 3, 4, 5])\n",
|
||
|
"\n",
|
||
|
"v1"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 7,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"numpy.ndarray"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 7,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"type(v1)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"The vector `v1` can now be multiplied with a scalar yielding a result meaningful in the context of linear algebra."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 8,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([ 3, 6, 9, 12, 15])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 8,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v2 = 3 * v1\n",
|
||
|
"\n",
|
||
|
"v2"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"To model a matrix, we use a `list` of (row) `list`s of values. Note how the output below the cell contains *two* levels of brackets `[` and `]`."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 9,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([[ 1, 2, 3, 4, 5],\n",
|
||
|
" [ 6, 7, 8, 9, 10]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 9,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1 = np.array([\n",
|
||
|
" [1, 2, 3, 4, 5],\n",
|
||
|
" [6, 7, 8, 9, 10],\n",
|
||
|
"])\n",
|
||
|
"\n",
|
||
|
"m1"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Now we can use the [np.dot() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/doc/stable/reference/generated/numpy.dot.html#numpy.dot) function to multiply a matrix with a vector to obtain a new vector ..."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 10,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([ 55, 130])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 10,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v3 = np.dot(m1, v1)\n",
|
||
|
"\n",
|
||
|
"v3"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"... or simply transpose it by accessing its [.T <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.T.html#numpy.ndarray.T) attribute."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 11,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([[ 1, 6],\n",
|
||
|
" [ 2, 7],\n",
|
||
|
" [ 3, 8],\n",
|
||
|
" [ 4, 9],\n",
|
||
|
" [ 5, 10]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 11,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1.T"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"The rules from maths still apply and it makes a difference if a vector is multiplied from the left or the right by a matrix. The following operation will fail."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 12,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"ename": "ValueError",
|
||
|
"evalue": "shapes (5,) and (2,5) not aligned: 5 (dim 0) != 2 (dim 0)",
|
||
|
"output_type": "error",
|
||
|
"traceback": [
|
||
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||
|
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
|
||
|
"\u001b[0;32m/tmp/user/1000/ipykernel_1264563/568665770.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mm1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||
|
"\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36mdot\u001b[0;34m(*args, **kwargs)\u001b[0m\n",
|
||
|
"\u001b[0;31mValueError\u001b[0m: shapes (5,) and (2,5) not aligned: 5 (dim 0) != 2 (dim 0)"
|
||
|
]
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"np.dot(v1, m1)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"## Indexing & Slicing"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"In order to retrieve only a subset of an array's data, we index or slice into it. This is similar to how we index or slice into `list` objects, in particular, if we deal with one-dimensional arrays like `v1`, `v2`, or `v3`."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 13,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([1, 2, 3, 4, 5])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 13,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Indexing may be done with either positive (`0`-based) indexes from the left or negative (`1`-based) indexes from the right.\n",
|
||
|
"\n",
|
||
|
"Here, we obtain the first and the last element in `v1`."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 14,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"1"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 14,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1[0]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 15,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"5"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 15,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1[-1]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Slicing uses the same `:` notation as with `list`s taking *start*, *stop*, and *step* values."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 16,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([2, 3, 4])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 16,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1[1:-1]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 17,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([3, 4, 5])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 17,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1[2:]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 18,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([1, 2, 3, 4])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 18,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1[:-1]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 19,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([2, 4])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 19,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1[1:-1:2]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 20,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([1, 3, 5])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 20,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1[::2]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Indexing and slicing become slightly more complicated when working with higher dimensional arrays like `m1`. In principle, we must provide either an index or a slice for *each* dimension."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 21,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([[ 1, 2, 3, 4, 5],\n",
|
||
|
" [ 6, 7, 8, 9, 10]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 21,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"For example, to slice out the first row of the matrix, we write `[0, :]`. The `0` implies taking elements in *only* the *first* row and the `:` means taking elements across *all* columns."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 22,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([1, 2, 3, 4, 5])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 22,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[0, :]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"For sure, we could also *not* leave out the *start* and *stop* values along the second dimension and obtain the same result. But that would not only be unneccessary but also communicate a different meaning, namely to \"take elements from the first through the fifth columns\" instead of \"take elements from all columns.\""
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 23,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([1, 2, 3, 4, 5])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 23,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[0, 0:5]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Whenever we take *all* elements in *later* dimensions (i.e., those more to the right), we may also drop the index or slice instead and keep only the *earlier* ones. However, the previous style is a bit more explicit in that we are working with a two-dimensional array."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 24,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([1, 2, 3, 4, 5])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 24,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[0]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"As another example, let's slice out elements across *all* rows but in only the *second* column. Colloquially, we can say that we \"slice out the second column\" from the matrix."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 25,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([2, 7])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 25,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[:, 1]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"If we wanted to slice out a smaller matrix from a larger one, we slice along both dimensions. Above, we have only sliced along one dimension while indexing into the other.\n",
|
||
|
"\n",
|
||
|
"For example, to obtain a 2x2 square matrix consisting of the two left-most columns in `m1`, we can write the following."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 26,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([[1, 2],\n",
|
||
|
" [6, 7]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 26,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[:2, :2]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Similarly, to slice out a 2x2 matrix consisting of the two right-most columns, we write the following."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 27,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([[ 4, 5],\n",
|
||
|
" [ 9, 10]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 27,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[-2:, -2:]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"To access individual elements as scalars, we combine two indexes along both dimensions.\n",
|
||
|
"\n",
|
||
|
"For example, to access the element in the lower-left corner, we write the following."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 28,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"6"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 28,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[1, 0]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"## Dimensionality vs. Shapes"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Both, the vectors `v1`, `v2`, and `v3`, and the matrix `m1` have the *same* **data type** from a technical point of view, namely `np.ndarray`."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 29,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"numpy.ndarray"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 29,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"type(v1)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 30,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"numpy.ndarray"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 30,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"type(m1)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"So, how can we tell that they have different dimensions without looking at how they are displayed below a code cell?\n",
|
||
|
"\n",
|
||
|
"The `np.ndarray` type comes with a couple of **properties** that we can access via the dot notation. Examples are `.ndim` and `.shape`.\n",
|
||
|
"\n",
|
||
|
"While `.ndim` simply tells us how many dimensions an array has, ..."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 31,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"1"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 31,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1.ndim"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 32,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"2"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 32,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1.ndim"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"... `.shape` reveals the structure of the elements. The one-element tuple `(5,)` below says that there is one dimension along which there are five elements ..."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 33,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"(5,)"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 33,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"v1.shape"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"... whereas the two-element tuple `(2, 5)` indicates that the array's elements are placed along two dimensions spanning a grid of two elements in one and five elements into the other dimension. We know such notations already from our linear algebra courses where we would call `m1` a 2x5 matrix."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 34,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"(2, 5)"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 34,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1.shape"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"There is a relationship behind the dimensionality of an array we are slicing and indexing and what we get back as a result: Whenever we index into an array along some dimension, the result will have one dimension less than the original.\n",
|
||
|
"\n",
|
||
|
"For example, if we start with a two-dimensional array like `m1` and slice along both dimensions, the result will also have two dimensions, even if it holds only one element."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 35,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([[ 1, 2, 3, 4, 5],\n",
|
||
|
" [ 6, 7, 8, 9, 10]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 35,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 36,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([[1]])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 36,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[:1, :1] # Note the double brackets"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"If, on the contrary, we slice only along one of the two dimensions and index into the other, the result is a one-dimensional array. So, both of the below slices have the *same* properties and we cannot tell if one of them was (part of) a row or column in `m1`."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 37,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([6, 7])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 37,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[1, :2]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 38,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([ 5, 10])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 38,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[:, -1]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Finally, indexing along both dimensions gives us back a scalar value."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 39,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"1"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 39,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"m1[0, 0]"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"## Array Constructors & Functions"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"[numpy <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/) provides various **constructors** (i.e., functions) to create all kinds of arrays.\n",
|
||
|
"\n",
|
||
|
"For example, [np.linspace() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/doc/stable/reference/generated/numpy.linspace.html#numpy.linspace) creates an array of equidistant numbers, often used to model the values on a function's x-axis. [np.pi <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/doc/stable/reference/constants.html#numpy.pi) is an alias for Python's built-in `math.pi`. The cell below creates `100` coordinate points arranged between $-3\\pi$ and $+3\\pi$."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 40,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([-9.42477796, -9.23437841, -9.04397885, -8.8535793 , -8.66317974,\n",
|
||
|
" -8.47278019, -8.28238063, -8.09198108, -7.90158152, -7.71118197,\n",
|
||
|
" -7.52078241, -7.33038286, -7.1399833 , -6.94958375, -6.75918419,\n",
|
||
|
" -6.56878464, -6.37838508, -6.18798553, -5.99758598, -5.80718642,\n",
|
||
|
" -5.61678687, -5.42638731, -5.23598776, -5.0455882 , -4.85518865,\n",
|
||
|
" -4.66478909, -4.47438954, -4.28398998, -4.09359043, -3.90319087,\n",
|
||
|
" -3.71279132, -3.52239176, -3.33199221, -3.14159265, -2.9511931 ,\n",
|
||
|
" -2.76079354, -2.57039399, -2.37999443, -2.18959488, -1.99919533,\n",
|
||
|
" -1.80879577, -1.61839622, -1.42799666, -1.23759711, -1.04719755,\n",
|
||
|
" -0.856798 , -0.66639844, -0.47599889, -0.28559933, -0.09519978,\n",
|
||
|
" 0.09519978, 0.28559933, 0.47599889, 0.66639844, 0.856798 ,\n",
|
||
|
" 1.04719755, 1.23759711, 1.42799666, 1.61839622, 1.80879577,\n",
|
||
|
" 1.99919533, 2.18959488, 2.37999443, 2.57039399, 2.76079354,\n",
|
||
|
" 2.9511931 , 3.14159265, 3.33199221, 3.52239176, 3.71279132,\n",
|
||
|
" 3.90319087, 4.09359043, 4.28398998, 4.47438954, 4.66478909,\n",
|
||
|
" 4.85518865, 5.0455882 , 5.23598776, 5.42638731, 5.61678687,\n",
|
||
|
" 5.80718642, 5.99758598, 6.18798553, 6.37838508, 6.56878464,\n",
|
||
|
" 6.75918419, 6.94958375, 7.1399833 , 7.33038286, 7.52078241,\n",
|
||
|
" 7.71118197, 7.90158152, 8.09198108, 8.28238063, 8.47278019,\n",
|
||
|
" 8.66317974, 8.8535793 , 9.04397885, 9.23437841, 9.42477796])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 40,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"x = np.linspace(-3 * np.pi, 3 * np.pi, 100)\n",
|
||
|
"\n",
|
||
|
"x"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Besides constructors, [numpy <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/) provides all kinds of **vectorized** functions. The concept of **vectorization** means that a function is executed once for *each* element in an array. Vectorized functions are one major benefit of using [numpy <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/): Not only are they optimized heavily on the C level (i.e., \"behind the scenes\") but also allow us to avoid writing explicit `for`-loops that are for some technical reasons considered \"slow\" in Python.\n",
|
||
|
"\n",
|
||
|
"For example, [np.sin() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/doc/stable/reference/generated/numpy.sin.html#numpy.sin) calculates the sine for each element in the `x` array. The resulting `y` array has thus the same `.shape` as `x`."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 41,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"array([-3.67394040e-16, -1.89251244e-01, -3.71662456e-01, -5.40640817e-01,\n",
|
||
|
" -6.90079011e-01, -8.14575952e-01, -9.09631995e-01, -9.71811568e-01,\n",
|
||
|
" -9.98867339e-01, -9.89821442e-01, -9.45000819e-01, -8.66025404e-01,\n",
|
||
|
" -7.55749574e-01, -6.18158986e-01, -4.58226522e-01, -2.81732557e-01,\n",
|
||
|
" -9.50560433e-02, 9.50560433e-02, 2.81732557e-01, 4.58226522e-01,\n",
|
||
|
" 6.18158986e-01, 7.55749574e-01, 8.66025404e-01, 9.45000819e-01,\n",
|
||
|
" 9.89821442e-01, 9.98867339e-01, 9.71811568e-01, 9.09631995e-01,\n",
|
||
|
" 8.14575952e-01, 6.90079011e-01, 5.40640817e-01, 3.71662456e-01,\n",
|
||
|
" 1.89251244e-01, -1.22464680e-16, -1.89251244e-01, -3.71662456e-01,\n",
|
||
|
" -5.40640817e-01, -6.90079011e-01, -8.14575952e-01, -9.09631995e-01,\n",
|
||
|
" -9.71811568e-01, -9.98867339e-01, -9.89821442e-01, -9.45000819e-01,\n",
|
||
|
" -8.66025404e-01, -7.55749574e-01, -6.18158986e-01, -4.58226522e-01,\n",
|
||
|
" -2.81732557e-01, -9.50560433e-02, 9.50560433e-02, 2.81732557e-01,\n",
|
||
|
" 4.58226522e-01, 6.18158986e-01, 7.55749574e-01, 8.66025404e-01,\n",
|
||
|
" 9.45000819e-01, 9.89821442e-01, 9.98867339e-01, 9.71811568e-01,\n",
|
||
|
" 9.09631995e-01, 8.14575952e-01, 6.90079011e-01, 5.40640817e-01,\n",
|
||
|
" 3.71662456e-01, 1.89251244e-01, 1.22464680e-16, -1.89251244e-01,\n",
|
||
|
" -3.71662456e-01, -5.40640817e-01, -6.90079011e-01, -8.14575952e-01,\n",
|
||
|
" -9.09631995e-01, -9.71811568e-01, -9.98867339e-01, -9.89821442e-01,\n",
|
||
|
" -9.45000819e-01, -8.66025404e-01, -7.55749574e-01, -6.18158986e-01,\n",
|
||
|
" -4.58226522e-01, -2.81732557e-01, -9.50560433e-02, 9.50560433e-02,\n",
|
||
|
" 2.81732557e-01, 4.58226522e-01, 6.18158986e-01, 7.55749574e-01,\n",
|
||
|
" 8.66025404e-01, 9.45000819e-01, 9.89821442e-01, 9.98867339e-01,\n",
|
||
|
" 9.71811568e-01, 9.09631995e-01, 8.14575952e-01, 6.90079011e-01,\n",
|
||
|
" 5.40640817e-01, 3.71662456e-01, 1.89251244e-01, 3.67394040e-16])"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 41,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"y = np.sin(x)\n",
|
||
|
"\n",
|
||
|
"y"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Next, let's use [matplotlib <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_plt.png\">](https://matplotlib.org/)'s [plt.plot() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_plt.png\">](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot) function to visualize the sine curve between $-3\\pi$ and $+3\\pi$."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 42,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"[<matplotlib.lines.Line2D at 0x7f008d3be6a0>]"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 42,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
},
|
||
|
{
|
||
|
"data": {
|
||
|
"image/png": "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
|
||
|
"text/plain": [
|
||
|
"<Figure size 432x288 with 1 Axes>"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {
|
||
|
"needs_background": "light"
|
||
|
},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"plt.plot(x, y)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"If we use only `10` equidistant points for `x`, the resulting curve does not look like a curve. There is a trade-off behind this: To make nice plots, we need a rather high granularity of data points. That, however, causes more computations in the background making the plotting slower. With toy data like the one here this is not an issue. For real life data that may be different."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 43,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"[<matplotlib.lines.Line2D at 0x7f008b2bff10>]"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 43,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
},
|
||
|
{
|
||
|
"data": {
|
||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYcAAAD4CAYAAAAHHSreAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAA/20lEQVR4nO29e3Bj93Xn+T0ACIIP8A2SuP1+sNlPQLJbkiNZlqVuSd0SIHl3k6ycSo0ySco7u+OaR2qzkctVTsoZVzmT2ji1s57NeOwkmmwqtsczXvdDLakltS3bsiW1Ht3sF0D2Q93NJsBXkwT4AkGc/eNeUBAJkiBxXwDOpwrFi3t/F/fwvs695/c730PMDEEQBEHIxWG1AYIgCIL9EOcgCIIgLEGcgyAIgrAEcQ6CIAjCEsQ5CIIgCEtwWW3Aemhra+OtW7dabYYgCEJJ8d577w0zs6+QtiXpHLZu3YqzZ89abYYgCEJJQUQfFdpWwkqCIAjCEsQ5CIIgCEsQ5yAIgiAsQZyDIAiCsARxDoIgCMISxDkIgiAISxDnIAiCICxBnEMF8+MPbmMkOWu1GUIOfYMJ/DQyaLUZQg7MjB+8exOTs2mrTTEVcQ4Vyq3RKfzbH5zD/32mz2pThBz+6nQU/8s/vIdkhd2I7MyHt8bwJ/+tBy/+6obVppiKOIcKJRpPAABOnh/AfEYKPtmFK7EEZtMZvHYpbrUpgkYkpl4rJ84NWGyJuYhzqFAimnMYTMzi3RujFlsjAMDM3DxuDE8CAI6fu2OxNUKW7LVyaWACV4eSFltjHuIcKpRoLIG2ejc8VQ6cOC83IjtwdSiJDAObWmrwZu8QxqfmrDZJgPqWvaGpBkSV9fYgzqFCicST2L+hEYf2dOBUTwzp+YzVJlU82VDfvz60C3PzjFcuxiy2SACASCyJ39jRivu3tuD4+TtgrowwrDiHCiQ9n8HVoSS6O7wIBxSMTKbwq2sjVptV8UTjSVQ5Cc8EFWxprcVxeaOznNHJFIaTs+q1ElTQN5hcCDOVO+IcKpCPRqeQSmewq8OLz3f7UF/tkhi3DYjGEtjeVg+3y4FQwI+3ro5gWIYaW0r2bW5XpxdH93fC6aCKuVbEOVQgUW30RXenF54qJ57Y24GXL8SQSktoyUoi8QR2dXoBAOGggvkM49QFCS1ZSdY5dHd40VpfjQd3tOL4uYGKCC2Jc6hAIvEEiIAdvnoAQCjox8RMGj/vHbLYssolOZvG7bvT2NWuHpPuDi92ttfjRIU8pdqVSCwBr8eFjoZqAEA4oODm6BR6+scttsx4xDlUINF4AltaalHjdgIAPrvTh8aaqop5XbYjvTnhCwAgIoQDCt65MYr4xIyVplU00XgC3R1eEBEA4Ml9nahyVkZoSRfnQERHiChCRH1E9EKe5d8iog+1T5SIxnKWzecsO6aHPcLKRONJ7OrwLnx3uxw4ur8Tpy/FMTM3b6FllUtvXB0/351zXEJBP5jVREXBfJhZvVY6Pz4mjbVVeGSXDyfPDyBT5smjRTsHInIC+DaAowD2AvgiEe3NbcPM/5aZ72HmewD8BwD/PWfxdHYZMz9TrD3Cysym53F9eBLdOSc8AIQCCiZT8zhzRXR9rCAST8BT5cCmltqFeTt89djrb5BRSxYxmJjF+PTcJxw2oF4rd8Zn8P7NuxZZZg56vDncD6CPma8xcwrA9wE8u0L7LwL4Jx22K6yDa0OTmM/wJ94cAOAz21vQVu+WG5FFROMJdLV74XTQJ+aHgwo+uDmGW6NTFllWuWRlMxZfK4f3dqDa5Sj70JIezmEDgFs5329r85ZARFsAbAPwRs5sDxGdJaJfE9EXltsIEX1Ja3d2aEg6TtfLwtC8RSe8y+nA0f1+vHFlUETfLCASS6Cro37J/FDADwA42SOhJbP5+Fr55HGpr3bhsd3tONkTK2tdMrM7pJ8D8CNmzg1sb2HmgwB+B8BfE9GOfCsy83eY+SAzH/T5fGbYWpZEYgm4HIRtbXVLloWDCmbmMnj9soi+mcnYVAqDidkl4QsA2NRSi3s2NZX9U6odicZViZnW+uoly8JBBcPJWbxdxsmjejiHfgCbcr5v1Obl4zksCikxc7/29xqAnwK4VwebhGWIxpPY7quD27X00B/c0ozOBg+OV5B+jB2Iap3RuzqXOgdAvRFdvDOBaxUk+mYHIosGbuTyaHc76txOHC/jwQJ6OId3AXQR0TYickN1AEtGHRHRbgDNAH6VM6+ZiKq16TYADwG4pINNwjJE44llT3iHg/B0wI+fRQdF9M1EIjmJVvl4+oBfFX0r4xuR3chkGL0rXCs1bicO7+3AqQsDmCtTXbKinQMzpwF8GcArAC4D+CEzXySirxNR7uij5wB8nz+ZWrgHwFkiOgfgDIBvMrM4B4OYSqVxc3Rq2ZsQoD6lzs0zXrkkmblmEY0l4K12wd/oybu8s9GD+7a2SGjJRPrHpjGVml8yqi+XcEDB2NQcftE3bKJl5qFLnwMzv8TMu5h5BzN/Q5v3NWY+ltPmz5j5hUXrvcXMB5g5qP39nh72CPnJjqXvWsE5BDc2YlNLjTylmkgkrnZGZxOt8hEO+NE7mFwYQSMYy8cjlZYOEsjy8K42eD2uspXxlgzpCmIhfLHC0xARIRRQ8Mu+YakvbQLMavhipWMCAEcP+OEgKQJkFtFB9VpZ6UGq2uXEkX2dePVirCyTR8U5VBC98QSqXQ5szkm0ykc4oIq+vSz1BAxnKDmLu1Nzy8a2s7TVV+PBHW04UUH1BKwkGktAafSgwVO1YrtwUEFiNo03o+U3vF6cQwURiSfR1VG/JNFqMXv8Xmz31clTqglEY0tlM5YjHPTjxsgULvRPGG1WxRNZJJuxHA/uaEVLnbssRy2Jc6ggorHlR1/kkhV9e/v6KAZF9M1QIosE91YiK/omZV2NJT2fwdXBZEEOW00e7cRrl+KYSpVX8qg4hwphfGoOsYmZgpwDoD6lMktmrtFEYwm01LnRlifRajFNtW483OXDiQoQfbOSGyNTSM1nVuxvyCUUUDA9N483ykyXTJxDhZDtYCvkaQgAdrZ7sbvTK6Elg4kOJlYcEbOYcNCP/rFpfHCrvEXfrKR3lbyTxdy/rQXt3uqyu1bEOVQI0TWEL7KEgwrevzmG23dF9M0ImBnRWKLgmxAAHN7TAbfLIVnsBpIthrWzvTCn7dSSR89EhpCYKZ/kUXEOFUI0lkB9tQvKMolW+QgHFABST8Ao+semMZmaX5PD9nqq8Fh3O072DJS16JuVLC6GVQihgIJUOoPTl8pHl0ycQ4UQiavhi5USrRazubUWwY2NkhBnENE1hi+yhIMKhhKzeOf6qBFmVTyRAgdu5PKpzU3Y0FRTVqElcQ4VADOv64QH1Ceinv5xXB+eNMCyyiYSWz1jPR+P7W5HrdsptTcMYDY9jxsjU2u+VtTkUT9+3juMsamUQdaZiziHCmA4mSoo0SofT2v1BKTQvf70xhPobPCgsWblRKvF1LidOLynA6d6ylf0zSoWimGtIdSXJRxUkM4wXr5QHsmj4hwqgN4CZDOWQ2mqwX1bmyW0ZACReGJdNyFALQJ0d2oOb10t33oCVrDeUB8A7FMasK2trmyuFXEOFUBkmepvhRIKKIjEEwsXjlA88xlG72AS3WsYxprLI90+eD2usopx24GVimGtRja09NbVYQwlSl+XTJxDBRCNZxOt3Ota/+iBTjhIQkt68tHIJFLpzLoddrXLiSf2duKVizHMpstP9M0qovHEssWwCiEcVJBh4NSF0n97EOdQAURiCXS1r22kUi7tXg8+s70Vx88PiOibTixXy3sthIN+JGbSeDNanvUErECVT1//MdnV4cWujvqykPEW51DmqJLQyXX1N+QSDiq4PjyJi3dE9E0Pogu1NdYXVgKAh3a2obm2SkJLOjGVSuPW6PS6+htyCQcUvHNjFAPj0zpZZg3iHMqcgfEZJGbTRT2hAsCRfZ1wOUiGT+pEJJ7A5pZa1Lpd6/6NKqcDR/b78drlOKZTEloqlmwxrGKvlVCwPJJHxTmUOYUU+CmE5jo3PtvVhhPnJLSkB4U
|
||
|
"text/plain": [
|
||
|
"<Figure size 432x288 with 1 Axes>"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {
|
||
|
"needs_background": "light"
|
||
|
},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"x = np.linspace(-3 * np.pi, 3 * np.pi, 10)\n",
|
||
|
"y = np.sin(x)\n",
|
||
|
"\n",
|
||
|
"plt.plot(x, y)"
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"[numpy <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/) provides further constructors. Most notably are the ones in the [np.random <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/doc/stable/reference/random/index.html#module-numpy.random) module that mirrors the [random <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/random.html) module in the [standard library <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/index.html): For example, [np.random.normal() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/doc/stable/reference/random/generated/numpy.random.normal.html#numpy.random.normal) and [np.random.gamma() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://numpy.org/doc/stable/reference/random/generated/numpy.random.gamma.html#numpy.random.gamma) return arrays whose elements follow the normal and gamma probability distributions."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "markdown",
|
||
|
"metadata": {},
|
||
|
"source": [
|
||
|
"Let us quickly generate some random data points and draw a scatter plot with [matplotlib <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_plt.png\">](https://matplotlib.org/)'s [plt.scatter() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_plt.png\">](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.scatter.html#matplotlib.pyplot.scatter) function."
|
||
|
]
|
||
|
},
|
||
|
{
|
||
|
"cell_type": "code",
|
||
|
"execution_count": 44,
|
||
|
"metadata": {},
|
||
|
"outputs": [
|
||
|
{
|
||
|
"data": {
|
||
|
"text/plain": [
|
||
|
"<matplotlib.collections.PathCollection at 0x7f008b235d00>"
|
||
|
]
|
||
|
},
|
||
|
"execution_count": 44,
|
||
|
"metadata": {},
|
||
|
"output_type": "execute_result"
|
||
|
},
|
||
|
{
|
||
|
"data": {
|
||
|
"image/png": "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
|
||
|
"text/plain": [
|
||
|
"<Figure size 432x288 with 1 Axes>"
|
||
|
]
|
||
|
},
|
||
|
"metadata": {
|
||
|
"needs_background": "light"
|
||
|
},
|
||
|
"output_type": "display_data"
|
||
|
}
|
||
|
],
|
||
|
"source": [
|
||
|
"x = np.random.normal(42, 3, 100)\n",
|
||
|
"y = np.random.gamma(7, 1, 100)\n",
|
||
|
"\n",
|
||
|
"plt.scatter(x, y)"
|
||
|
]
|
||
|
}
|
||
|
],
|
||
|
"metadata": {
|
||
|
"kernelspec": {
|
||
|
"display_name": "Python 3 (ipykernel)",
|
||
|
"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.8.12"
|
||
|
},
|
||
|
"toc": {
|
||
|
"base_numbering": 1,
|
||
|
"nav_menu": {},
|
||
|
"number_sections": false,
|
||
|
"sideBar": true,
|
||
|
"skip_h1_title": false,
|
||
|
"title_cell": "Table of Contents",
|
||
|
"title_sidebar": "Contents",
|
||
|
"toc_cell": false,
|
||
|
"toc_position": {},
|
||
|
"toc_section_display": true,
|
||
|
"toc_window_display": false
|
||
|
}
|
||
|
},
|
||
|
"nbformat": 4,
|
||
|
"nbformat_minor": 4
|
||
|
}
|