1364 lines
92 KiB
Text
1364 lines
92 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/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (2.0.0)\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/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (3.9.1)\n",
|
|
"Requirement already satisfied: contourpy>=1.0.1 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (1.2.1)\n",
|
|
"Requirement already satisfied: cycler>=0.10 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (0.12.1)\n",
|
|
"Requirement already satisfied: fonttools>=4.22.0 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (4.53.1)\n",
|
|
"Requirement already satisfied: kiwisolver>=1.3.1 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (1.4.5)\n",
|
|
"Requirement already satisfied: numpy>=1.23 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (2.0.0)\n",
|
|
"Requirement already satisfied: packaging>=20.0 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (24.1)\n",
|
|
"Requirement already satisfied: pillow>=8 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (10.4.0)\n",
|
|
"Requirement already satisfied: pyparsing>=2.3.1 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (3.1.2)\n",
|
|
"Requirement already satisfied: python-dateutil>=2.7 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from matplotlib) (2.9.0.post0)\n",
|
|
"Requirement already satisfied: six>=1.5 in /home/instructor/Repositories/intro-to-data-science/.venv/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\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)",
|
|
"Cell \u001b[0;32mIn[12], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdot\u001b[49m\u001b[43m(\u001b[49m\u001b[43mv1\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mm1\u001b[49m\u001b[43m)\u001b[49m\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": [
|
|
"np.int64(1)"
|
|
]
|
|
},
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"v1[0]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"np.int64(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": [
|
|
"np.int64(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": [
|
|
"np.int64(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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\n",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"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+CmE5jo3PtvVhhPnJLSkB4Uq5K5GOOjHVKr8RN+sQK9rZVtbHfZvaCh5GW9xDmVONFvusF2HG1FA0UTfxor+rUpmNj2P68OT6O5cf0gpywPbWuHzVouMtw5EY4UVwyqEcEDBuVtjuDlSurpk4hzKnEg8gY6GajTWri3RKh+P7+uA2+mQGHeRXB+eRDrDurw5OB2Epw/48caVQSRny6uegNlE4gnsbF+9GFYhLCSP9pTutaKLcyCiI0QUIaI+Inohz/LfI6IhIvpQ+/xhzrLniahX+zyvhz3Cx0Tj+oQvAKDBU4XPd/tw8ryIvhVDVKfYdpZw0I/ZdAavlZHomxX0xgsr8FMIG5tr8anNTSWtnlu0cyAiJ4BvAzgKYC+ALxLR3jxNf8DM92if72rrtgD4UwAPALgfwJ8SUXOxNgkq8xlGX4EVrQolHFQwmJjFuzdE9G29RGMJOB2E7b61J1rl495NzVAaPfJGVwQLxbCK7G/IJRxUcHlgAn2DSd1+00z0eHO4H0AfM19j5hSA7wN4tsB1nwRwmplHmfkugNMAjuhgkwDg1ugUZuYyup7wh/a0o6bKKTeiIojEE9jWVodqV+GS0CvhcBBCQQVv9g5hfKp86gmYyVqLYRXCUwf8IELJ9gfp4Rw2ALiV8/22Nm8x/xMRnSeiHxHRpjWuCyL6EhGdJaKzQ0NDOphd/hQrm5GPWrcLh/a049SFGNIi+rYuovG1FfgphFDAj7l5xisXy0P0zWwisbUXw1qNjgYPHtjWguPn7pTkCD+zOqSPA9jKzAGobwcvrvUHmPk7zHyQmQ/6fD7dDSxHsiOVugqsaFUooYCC0cmUiL6tg+nUPG6OThWV/JaPAxsasaW1VvJQ1kk0vvZiWIUQCii4OjSJK7HS0yXTwzn0A9iU832jNm8BZh5h5qwS1XcBfLrQdYX1E4knsKmlBnXV60+0ysfnu32or3aV7OuylfQNJsGsb/gCyBV9G8FwsvRF38wmGk+ga43FsArh6P5OOB1UkmFYPZzDuwC6iGgbEbkBPAfgWG4DIvLnfH0GwGVt+hUATxBRs9YR/YQ2T9ABPUdf5OKpcuKJfR14+YKIvq2VyDpqeRdKOKhgPsM4VSb1BMwiWwzLiGultb4aD+1sw4kS1CUr2jkwcxrAl6He1C8D+CEzXySirxPRM1qzf0VEF4noHIB/BeD3tHVHAfw5VAfzLoCva/OEIkmlM7g6lNS1vyGXcEDBxEwaPxfRtzURjSfgdjmwRYdEq8V0d3jR1V5fkk+pVlJMMaxCCAX8uDk6hfO3xw35faPQpc+BmV9i5l3MvIOZv6HN+xozH9Omv8LM+5g5yMyPMvOVnHX/lpl3ap+/08MeAbgxol+iVT4e2tmGptoqCS2tkUgsgZ2+eric+nf3qaElBe/eGEVsfEb33y9XojrJZizHk/s6UeUsvdCSZEiXKQujLwxyDm6XA0f2deL0pThm5iS0VChqUqK+ndG5hIJ+MAMne0o3+cpssteK3oMEsjTWVOGRXT6c7BlApoSSR8U5lCnRuL6JVvkIBxVMpuZxRkTfCmJiZg4D4/omWi1mh68ee/0N8ka3BnoHE2iurYKvvtqwbYSDCgbGZ/DezbuGbUNvxDmUKdF4Altba+Gp0ifRKh8PbGtBW71bhk8WSG8R9YnXQjio4IObY7g1Wrqib2YS0RRy9R6plMvhPR3wVDlKqpqiOIcyJapDgZ/VcDkdeOqAH69fFtG3QojE9NVUWo5QVvStxCWjzYCZTblW6qpdeGx3O072DJRM8qg4hzJkZm4eN0Ym0aWDTPdqhIMKZtMZvH5ZRN9WIxpPoM7txIamGkO3s6mlFvdsapLQUgHcGZ9BUodiWIUQDigYTqbw9vXSGJApzqEMWUi0MvhpCAA+vbkZnQ0i+lYI0XgCOzu8cOggCb0a4aCCi3cmcG2oNEXfzEKPWt6F8ujudtS5nSXjtMU5lCFGj1TKxeFQM3N/FhXRt9VQNZWMG6mUy9MLom8SWlqJhWJYJhwXT5UTj+/twKkLMcyVQGhJnEMZEh1MwO10YGur/olW+QgFFVX07ZJk5i7HcHIWw8mUKQ4bADobPbhvawuOlajom1lki2E11bpN2V44qGBsag6/6LN/8qg4hzIkGktgR7sxiVb5CG5sxKaWGgktrYDRiVb5CAcV9A0mFyQ7hKXoWQyrEB7u8qHB4yqJa0WcQxkSjSdNeU3OQkQIBxS8dXUEIyL6lpds+MLoYay5HN3fCQcBJ0q4GpmRzGfYMP2x5XC7HDiyvxOvXrR/8qg4hzIjMTOH/rFpU5+GAFWaWETflic6mERjTRV8XuMSrRbTpom+HT8voaV83Bqdwmw6Y8m1kpxN42dRe9elEedQZmTrE5v5NAQAe/xe7PDVlcxIDLOJaqqfRiZa5SMU8OOjkSlc6J8wdbulgJEKuSvx4I5WtNS5bR9aEudQZvRaENsGPhZ9e/v6KOITIvqWCzMjEk9gV6d5ob4sC6Jv4rSXYFQxrNVwOR04ur8Tr18exFTKvsmj4hzKjEg8gVoTEq3yEdZE314S0bdPEJuYQWImbfrbHAA01brxcJcPJ8+XluibGRhVDKsQwkEF03PzeP2yfXXJxDmUGdF4Al3t9aYkWi1mZ7sXe/wNtn9dNhsz807yEQ760T82jQ9ulY7omxkYUcu7UO7b2oKOhmpbXyviHMqMSMy4Aj+FEAr48f7NMdy+K6JvWXrj5mgqLcfhPR2odjlwXEYtLZBKZ3BtaBJdFh0Tp4Pw1AE/fhodwsSMPZNHxTmUEaOTKQwnZ03vb8glHFAAACclM3eBSDwBn7cazXXmJFotxuupwqPdqujbvISWAHxcDMuqNwdADS2l0hmcvmhPXTJxDmWEmToxy7G5tRbBjY3SAZqDleGLLOGggqHELN6+PmKpHXbB6lAfANy7qQkbmmpsO8JPnEMZYUUWbj7CQQUX+idwfXjSUjvsQCbDpmfh5uOx3e2odTtFa0nDjGJYq0FECAX9+HnvMO5OpiyzYzl0cQ5EdISIIkTUR0Qv5Fn+R0R0iYjOE9HrRLQlZ9k8EX2ofY7pYU+lEokl0OBxod3ERKt8PJ2tJ2DjzjazuHV3CjNzGXRbMIw1lxq3E4f3dOBUz0BJiL4ZTSRmfDGsQggHFKQzjFcu2i95tGjnQEROAN8GcBTAXgBfJKK9i5p9AOAgMwcA/AjAv89ZNs3M92ifZ4q1p5KJxhPo7jQ/0Wox/sYa3Le1WUJL+Dgp0aqOz1zCQQV3p+bwyxIQfTOa3kFrB25k2ac0YFtbnS2vFT3eHO4H0MfM15g5BeD7AJ7NbcDMZ5g5O3zl1wA26rBdIQdmXih3aAfCQQXReHIhtlupZEN9Zida5eNzu9rg9bgqPrSULYZlh2tF1SXz41dXRzCUsJcumR7OYQOAWznfb2vzluMPAJzK+e4horNE9Gsi+oIO9lQkg4lZTMykLe9vyHJ0v18VfbPhE5GZRGIJbGiqgddTZbUpqHY58eS+TrxyMYbZtL1F34zEzGJYhRAKKsgwcOqCvZy2qR3SRPS7AA4C+Muc2VuY+SCA3wHw10S0Y5l1v6Q5kbNDQ/YWrLICO4y+yMXnrcZv7GjFifMDFS36lg312YVQwI/ETBpvRis3tGS3a2VXhxfdHV7bJcTp4Rz6AWzK+b5Rm/cJiOgwgK8CeIaZF96fmLlf+3sNwE8B3JtvI8z8HWY+yMwHfT6fDmaXF3YYxrqYcEDB9eFJXLxTmaJvc/MZXB2yR2w7y0M729BcW2W7G5GZROPmFsMqhHDQj3dv3MXA+LTVpiygh3N4F0AXEW0jIjeA5wB8YtQREd0L4D9BdQyDOfObiaham24D8BCASzrYVHFEYgm01VejxaJEq3wc2d8Jl4Mq9kb00cgk5ubZ1Noaq1HldODIfj9euxzHdKoyQ0vReALbfXWmFcMqhJANk0eL3jvMnAbwZQCvALgM4IfMfJGIvk5E2dFHfwmgHsB/XTRkdQ+As0R0DsAZAN9kZnEO60ANX9jnJgRkRd/aKja0FIlZK5uxHOGgH1Opebxxxb6ib0YSjSdtFeoDgK1tdTiwodFWD1K6uE5mfomZdzHzDmb+hjbva8x8TJs+zMwdi4esMvNbzHyAmYPa3+/pYU+lkcmwbYbmLSYUUNA/No33b45ZbYrpROIJOAjYaYORSrk8sK0VPq+9Rd+MwqpiWIUQCvhx7vY4bo7YQ5fMPu9VwrrpH5vGVGrelif84/s64HY5KnLUUjSWwNbWOssTrRbjdBCePuDHmcggEjYVfTMKq4phFUI2edQuOQ/iHMoAu42+yKXBU4VHu9V6ApUm+mYH2YzlCAf9mE1n8Nple4q+GYVdJGbysbG5Fp/e0mybPBRxDmXAQrlDG3V85hIKKBhMzOLdG6NWm2IaHyda2fOY3LupGUqjBycqTMY7Gk+gpsqaYliFEAr4cXlgAn2D1iePinMoA6Jx+yRa5ePQnnbUVDkrKsZ9dSiJDJtfn7hQHA5CKKjgzd4hjE3ZT/TNKNS3OWuKYRXC0wf8IIItam+IcygDovGkbZ9QAaDW7cKhPe04dSGGdIWIvi2EL2waVgLUPJS5eXuKvhmF1cWwVqO9wYMHtrXgxPk7lo/wE+dQ4qTnM7hq05FKuYSDCkYnU3jramXUE4jEkqhyEra2WScJvRr7NzRgS2utbWLcRjOSnLW8GFYhhIMKrg5N4vKAtaElcQ4lzo2RKaTmM7Z3Do/s8sFb7aqY0FI0nsAOXz2qbJRotRhV9E3BL/uGMZy0l+ibEUQtLtdaKEf3++F0kOUj/Ox75goFYefRF7l4qpx4fF9HxYi+ReMJW8h0r0Yo6NdE38o/tNQ7aN9Rfbm01Lnx0M42HLc4tCTOocSJxBIgGyZa5SMcVDAxk8bPy1z0LTmbxu270+i2cT9Qlu4OL7ra6yvijS5bDKujwdpiWIUQDvhxa3Qa526PW2aDOIcSp3fQnolW+fjszjY01VbZJsnHKHptKIK4HESEUEDBuzdGERufsdocQ7FLMaxCeGJfJ9xOh6XVFMU5lDiRWMIWhWQKocrpwNH9nXjtUnmLvpVKqC9LKOgHM3Cyp3w7pu1WDGs1Gmuq8LldPpw4P4CMRcmj4hxKGDXRaqpkbkKAOnxyMjWPM5HyFX2LxpPwVDmwqdk+ktArscNXj31KQ1mHluxWDKsQwkE/YhMzeO/mXUu2L86hhLk2NIn5DJfM0xAAPLC9FW311ZaPxDCSaDyBrnavbROt8hEKKPjw1hhujdpD9E1vshIzXe2lc60c3tMBT5XDMqctzqGEKbXwBZAVfevE65cHkZxNW22OIZRS+CJLSBN9K9ech6jNJWbyUVftwqHdHXipZ8CS5FFxDiVMNJ5QE61a7ZtolY9QUFFF3y6Vn+jb3ckUBhOztqutsRqbWmpxz6amsg0tZYthtdbbf6RSLqGAH8PJFN6+br4umTiHEiYaT2BbWx3crtI6jJ/e3Ax/o6csQ0t2LNdaKOGggksDE7g6lLTaFN2xYzGsQnh0dzvq3NbokpXWXUX4BBEbS0KvhMNBCAX8+Fl0CONT5VVPIDqo1QsooVBflqzoW7kptdq5GNZqeKqceGJfJ16+GEMqbW5oSZxDiTI5m8at0WlbC7utRCgr+napvDJzo7EEvNUudDZ4rDZlzXQ2enDf1hbLM3P1xs7FsAohFPBjbGoOv+wzN3lUnEOJ0qs9odpVEno1Ahsbsbmltuxi3JF4ArtKJNEqH+Gggr7B5EKNkHLAzsWwCuHhLh8aPObrkolzKFFKQRJ6JdTMXD/eujqCkTIRfWNmW1d/K4Sj+zvhIJSV07Z7MazVcLscOLK/E69eimNmzrzkUV2cAxEdIaIIEfUR0Qt5llcT0Q+05W8T0dacZV/R5keI6Ek97KkEorEEql0ObGopjUSrfISDCuYzXDaib0OJWYxNzZWEptJytNVX46GdbThxfqBsQkt2L4ZVCOGgguRsGj+NDJm2zaKdAxE5AXwbwFEAewF8kYj2Lmr2BwDuMvNOAN8C8BfaunsBPAdgH4AjAP6j9nvCKkTiCXR11MNZQolWi9nd6cXOMhJ9W5CELtFQX5ZwQMFHI1Po6bdO9E1P7F4MqxB+Y3srWuvcpo7w0+PN4X4Afcx8jZlTAL4P4NlFbZ4F8KI2/SMAh0gNyj4L4PvMPMvM1wH0ab9nCN8+04dvnrpi1M+bSqmHL4CPQ0vv3BhFfKL0Rd8iJTyMNZcn93Wiykll4bRLpRjWaricDhzVkkenUuYkj+rhHDYAuJXz/bY2L28bZk4DGAfQWuC6AAAi+hIRnSWis0ND63u1ujkyhX/41Q1T43ZGMD41h/jEbMn2N+QSDiqq6FsZZOZGYwm01rnRVmKJVotprK3C57p8OGmh6JtelEoxrEIIBxQoTR7cvjttyvZKpkOamb/DzAeZ+aDP51vXb4SDqujbT0tc9C2aLVpS4uELQBV92+NvKIuEuFLNO8lHKOjHnfEZfHDLGtE3vShFiZnluH9bC177o0dMO8f0cA79ADblfN+ozcvbhohcABoBjBS4rm58ZnsLWuvcOF7iST6lPjRvMeGgH+/fLG3RN2ZGr1YvoBw4vKcD1S5HWVwrpVIMazWIyNQh0no4h3cBdBHRNiJyQ+1gPraozTEAz2vTvwngDVaHQhwD8Jw2mmkbgC4A7+hgU15cTgeeOuDH61fimCxh0bdoPIH6aheUxtJLtMpH6IACoLTrCfSPTWOyhBOtFuP1VOHR7nac7BnAfAmHlkqpGJbdKNo5aH0IXwbwCoDLAH7IzBeJ6OtE9IzW7HsAWomoD8AfAXhBW/cigB8CuATgZQD/kpkN7RAIBfyYmcvgtculK/qmqn7Wl2yi1WI2t9YiuKmppENLpaj6uRrhoIKhxCzevj5itSnrppSKYdkNXfocmPklZt7FzDuY+RvavK8x8zFteoaZf4uZdzLz/cx8LWfdb2jrdTPzKT3sWYn7trago6G6ZF+Xs4lW5RK+yBIO+HGhfwLXhyetNmVdRGLqMNauMnlzAIDHdrej1u0s2WulFIth2YmS6ZDWC1X0TcGb0SGMT5ee6NtwMoW7U3NlE77I8nS2nkCJDp+MxhPwN3rQWFO6iVaLqXE7cXhPB16+MIA5C+oJFEspFsOyExXnHAA1tJSaz+DVi6WXmVvKktAr4W+swf2a6FspUooFfgohHFRw1wLRNz0op5FKVlCRzuGeTU3Y2FxTklWvym2kUi6hoB/ReHLhfywV5jOMvqFkWd6EPrerDV6PqyRDS6VaDMsuVKRzUDNzFfyibxijkymrzVkT0XgCLXVutNW7rTZFd47u98NBKLmO6Y9GJpFKZ8qy47Pa5cST+zrx6sUYZtOllTxaqsWw7ELF7rVw0K+JvpXWE5GaaFU+I5Vy8Xmr8eCONhw/V1r1BMo9fBEOKkjMpvEzE0Xf9KCckhKtoGKdw15/A7b76kqq6pWaaFX6OjErEQr4cWNkChfvTFhtSsFEYsmySbTKx4M7WtFcW1VSYdhSL4ZlByrWOWRDS7++PoLBEhF9uzM+g+Rsuqydw5H9nXA5Skv0LRpPYHNLLWrdLqtNMYQqpwNHD/hx+lLcNNG3Yin1Ylh2oGKdA6COrWcGXiqRzNxorLzDFwDQVOvGw12lVU+gHBRyVyMU8GN6bh5vXCkNXbJSL4ZlByraOXR1eLG704vjJfK6vCAJ3V7eJ3w4qKB/bBrv3xyz2pRVmU3P4/rwZFllRufjgW2t8HmrSyYMWw7FsKymop0DoN6I3vvoLvrHzJHBLYZoLIHOBg8aa8sn0Sofj+/tgNvlKInQ0vXhSaQrINHK6SA8fcCPNyKDSMzYP3m0HIphWU3FO4eQlpl7sgSGT0YH1RO+3FFF33x4qQRE3yIVEOrLEg76kUqXhi5ZJYT6jKbincOW1joENjbaPslnPqOOVKqUGGo4qGAwMYt3ro9abcqKROMJuByE7W3l77Tv3dSMDU01tr9WyqkYlpVUvHMA1ApLPf3juGFj0bebo1OYTWcqZvTFY7vbUVPltL2cRjSerJhEK4eD8HTAjzejQxibsm/yaDkVw7KS8j+jC2BB9M3GN6KF8EWFPA3Vul04vLcDL1+I2Vr0rdLCF+GAgnSG8YqNdcnKWWLGTMQ5AFCaanBwS7OtX5ezQ/Mqoc8hSyjgx+hkCm9dtWc9galUGjdHpyrqJrR/QwO2ttba/lopp2JYViHOQSMcVBCJJxZuwnYjGk9gU0tN2SZa5eORXT54q122lfHuG0yCGejurByHnU0efevqMIaTs1abk5dyK4ZlFeIcNI4e6FRF32x6I4rGExUTUsriqXLiiX2deNmmom/RuJaFW2HHJRxUkGHglA2TR8u1GJYViHPQaPd68JntrbbMzE2lM7g2NFlxNyFAlfFOzKTxZtR+9QSi8QTcLge2VJgkdHenF13t9bYMLZVrMSwrEOeQQyig4NrwpO1E37KJVpX4NPTZnW1oqq2y5WCBSCyBnb7KTLQKBxW8+9EoBsbtlTxarsWwrKAo50BELUR0moh6tb/NedrcQ0S/IqKLRHSeiP7nnGV/T0TXiehD7XNPMfYUS1b0zW7qk5EKPuGrnA4c3d+J05fimE7ZK7RUyeGLkKZLdtJu14qMVNKNYt8cXgDwOjN3AXhd+76YKQD/jJn3ATgC4K+JqCln+R8z8z3a58Mi7SmKljo3Htppv3oCvfEEnA7Cdl9lhS+yhAMKplLzOBOxj+jb+PQcBsZnKvYmtN1Xj31Kg+0epMq5GJbZFOscngXwojb9IoAvLG7AzFFm7tWm7wAYBOArcruGkRV9++DWmNWmLBCJJbC1tRbVLqfVpljCA9tb0VZfbSutpb7BrGxG5YxUWkw4qODDW2O4NTpltSkLRMu4GJbZFOscOpg5++gQA9CxUmMiuh+AG8DVnNnf0MJN3yKi6iLtKZon9nXA7XTYSn2yksMXQFb0rRNvXBlEctYe9QQiscocqZTL0wfU5FG7ZLGrI5UqR2LGaFZ1DkT0GhFdyPN5Nrcdq3GYZWMxROQH8A8A/jkzZ1NevwJgN4D7ALQA+JMV1v8SEZ0lorNDQ8aVK2zwVOGRbh9O9txBxgaib9OpeXxUYYlW+QgHFcymM3jtkj1E36LxBOrcTmxoqrHaFMvY1FKLezc32eZBKlsMq6vCrxW9WNU5MPNhZt6f5/MTAHHtpp+9+ecNChNRA4CTAL7KzL/O+e0BVpkF8HcA7l/Bju8w80FmPujzGRuVCgcVxCdm8e4N60XfFhKtKvyE/9TmZvgbPbYJLUViCXR1eCs+fBEOKLg0MIGrQ0mrTamIYlhmUmxY6RiA57Xp5wH8ZHEDInID+DGA/8LMP1q0LOtYCGp/xYUi7dGFQ7vb4aly2OJ1+WPZjMo+4R0OQijgx5u9Qxifsr6eQCUmJebj6YAfRLDF20OlFMMyi2KdwzcBPE5EvQAOa99BRAeJ6Ltam98G8DkAv5dnyOo/ElEPgB4AbQD+XZH26EJdtQuH9nTgVE8MaYtF36LxBNxOB7a2SkWrcFDB3Lz1om/DyVmMTKZE9RNAR4MH929twbFz/ZaP8IvGK6MYllkU5RyYeYSZDzFzlxZ+GtXmn2XmP9Sm/19mrsoZrrowZJWZH2PmA1qY6neZ2fp3U41wQMHIZAq/umat6FsknsCO9nq4nJKveGBDIza31Fr+Rif1iT9JKKjg6tAkrsSs1SWLxhPisHVE7jjL8PluH+qrXZbHuKOxBLorSIl1JYgI4aAfb10dsVT0LbqQaCXHBQCO7u+E00GWZrFni2HtapdjohfiHJbBU+XEE1o9gVTamtDSxMwc7ozPyNNQDqGAgvkM49QF60JLkXgSTbVV8HktH3ltC9rqq/HgjlYcP2edLlmlFcMyA3EOKxAK+jExk8bPe40bOrsSvVnVT+lgW2B3pxc72+stVc/NFvip9JFKuYQDCm6OTqGnf9yS7VdaMSwzEOewAp/d6UNjTZVlEgELsW15GlqAiBAOKHjnxihi4zOmb39BElpuQp/gyX2dqHKSZWHY3goshmU04hxWwO1SRd9evRjDzJz5om+RWAK1FZ5olY9QUBN9s6CeQGxiBomZtIQvFtFYW4XPdflw4vyAJcmjkXgCm1tqK6oYltGIc1iFUEDBZGoeZ66YL/oWjauJVo4KlIReiR2+euz1N1jSAbqg+ikdn0sIBxUMjM/g/Zt3Td92VlNJ0A9xDqvwme0taKt3WxJaUsMXcsLnIxT044Ob5ou+Sb2A5Tm8twPVLofpoaVKLoZlJOIcVsHldODofj9evxLHpImibyPJWQwnU3LCL0M4oAAwP7QUiSXR7q1Gc51IQi+mvtqFx3a342RPDPMmhpYquRiWkYhzKIBwUMHMXAavXTZP9K1S6xMXyqaWWgQ3NZn+lNo7WNkKuasRDioYTs7ibROTR+VtzhjEORTAwS3N6GzwmFozV0YqrU444MfFOxO4ZpLoWybDC8NYhfw82t2OWrcTx00Mw0YrvBiWUYhzKACHg/B0wI+fRQcxPm2O6FsknkBjTRXaJdFqWUIBRRV9M+lGdOvuFGbmMtLxuQI1bice39uBUxcGMGeSLlmlF8MyCnEOBZIVfXvVJNE3VTZDEq1WorPRg/u2tJgWWpL6xIURDigYm5rDL/qGTdlepRfDMgpxDgUS3NiITS01prwuZxOtJKFndcJBP3oHkws3biMR+fTCeHhXG7welyky3lIMyzjEORQIESEUUPDLvmGMTqYM3VZ8YhYTM2l5GiqAI/v9cBBMeXuIxpPY2FyD+mpJtFqJapcTR/aZkzx6dUiKYRmFOIc1EF4QfTP2iSgioy8KxuetxoM72nDi/B3DRd9ENqNwQkEFidk03owaq0u2EOqTByndEeewBvb4vdjuqzP8KTUqse01EQ76cWNkChf6Jwzbxtx8BleHkhJSKpAHd7Sipc5teBg2WwxrS4sUw9IbcQ5rICv69vb1UQxOGCf6Fokn0FZfjRZJtCqIJ/d1wuUgQ4sA3RiexNw8o7tT+oEKocqp6pK9dimOqZRxyaNSDMs4ZI+ukbAJom+98YTchNZAU60bn9vlw0kDRd8k1Ld2QgEF03PzeMNAXTIphmUc4hzWyM52L3Z3eg0bW68mWiXlJrRGQgE/+sem8cEtY0TfovEkHKSK/gmFcf+2FrR7qw0LwyakGJahiHNYB+Gggvc+uov+sWndf/v23WlMz81Lx+caeXxvB9wuh2FZ7NFYAlvb6uCpkkSrQnE6CE8d8ONMZAiJGf2TR7MSM3KtGENRzoGIWojoNBH1an+bl2k3T0Qfap9jOfO3EdHbRNRHRD8gopIIsi+IvhkQ414IX8jT0JrweqrwWHc7TvYMGCL6Fo0npCLfOggHFaTSGZy+pL8umWgqGUuxbw4vAHidmbsAvK59z8c0M9+jfZ7Jmf8XAL7FzDsB3AXwB0XaYwqbW2sR3NhoyFPqQqKV1AtYM6GgH0OJWbx9XV/Rt5m5edwYmRSHvQ4+tbkJG5pqDAktSTEsYynWOTwL4EVt+kUAXyh0RVJ1IR4D8KP1rG81oYCCnv5x3Bie1PV3o/EENjTVwOup0vV3K4HHdquib3r3B/UNJpGRRKt1oSaP+vHz3mGMTembPCrFsIylWOfQwczZKzEGoGOZdh4iOktEvyaiL2jzWgGMMXN2nNttABuW2xARfUn7jbNDQ8Ym1hTC0wE/AOhejSwSk4pW66XW7cKhPR041aOv6FvvYFYhV47LeggHFaQzjJcv6KtLFo0nZaSSgazqHIjoNSK6kOfzbG47VtNTlwv2bmHmgwB+B8BfE9GOtRrKzN9h5oPMfNDn8611dd1Rmmpw39ZmXUNLc/NaRSsJX6ybcMCPu1NzeOuqfqGlSCypJlq1iiT0etinNGBra62ub3RqMaxZ6W8wkFWdAzMfZub9eT4/ARAnIj8AaH/zDmhm5n7t7zUAPwVwL4ARAE1ElBWq2Qigv+j/yERCAQWReGKhn6BYPhqZRGo+I+GLInik2wdvtUvXGHc0nsB2Xx2qJNFqXRARwkEFb10dxlBiVpfflGJYxlPs2X4MwPPa9PMAfrK4ARE1E1G1Nt0G4CEAl7Q3jTMAfnOl9e3M0QOdcBBwQqcbUSQmJ3yxVLuceGJfJ165GMNsWh/RNzXUJ8ekGMJBBRmGbrpkUgzLeIp1Dt8E8DgR9QI4rH0HER0kou9qbfYAOEtE56A6g28y8yVt2Z8A+CMi6oPaB/G9Iu0xlXavB5/Z3orj5wd0EX2LxhMgAnbKSKWiCAf9SMyk8Wa0+HoCydk0+sem5SZUJLs6vNjVUa+bjHdUimEZTlHOgZlHmPkQM3dp4adRbf5ZZv5DbfotZj7AzEHt7/dy1r/GzPcz805m/i1m1ued00TCQQXXhydx8U7xom/ReAJbWyXRqlge2tmG5toqXUJLvTKWXjfCAQXv3BjFwHjxyaNZhVwphmUcEkQtkiM6ir5F4jJSSQ+qnA4c2e/Ha5fjmE4VF1paCF+IcyiaUDCbPFrc2wMzq6E+GT1mKOIciqS5zo3PdrXhxLniQkszc/O4MTwpNyGdCAf8mEoVL/oWiSVRU+XExmZJtCqWbW112L+hoWgZ72wxLHmbMxZxDjoQDiia6NvYun/j6pCaaCX1AvThge2taKsvXvQtW65VEq30IRxQcO7WGG6OTK37N0Qh1xzEOejA4/s64HY6iups682KiEnHpy44HWpm7pnIYFGib9G4jFTSk4Xk0Z71O23pBzIHcQ460OCpwue7fThx/s66Rd8i8QSqnIStkmilG6GAH7PpDF67vD7Rt7uTKQwmZiXUpyMbm2vxqc1NRSWPRmIJ+LxSDMtoxDnoRDioYDAxi3dvjK5r/Wgsge1t9XC75JDoxac2N0Np9Kz7jS4qCrmGEAoouDwwgb7B5LrWl1re5iB3Ip04tKcdNVXOdWstReIJuQnpjMNBeDrgx5u9Q+sSfftYElpGxejJ0wE/iNanS5YthtUlx8RwxDnohCr61o5TPTGk1yj6Njmbxu2709glyW+6Ew4qmJtnvHJx7aJvkXgCXo8LnQ0eAyyrXDoaPHhgWwuOn7uz5hF+UgzLPMQ56EgooGBkMoVfXVub6Fuv9notbw76c2BDI7asU/RNVf2URCsjCAUUXB2axJXY2nTJJNRnHuIcdOTz3T7Ur0P0LRqTRCujyNYT+GXfMIaThSfgM7M6UkluQoZwdH8nnA5a87USkWJYpiHOQUc8VU48sa8DL1+IIZUuPLQUiSfgqXJgU0utgdZVLh+LvhUeWhpKzGJsak4ctkG01lfjwR2tOLFGXTIphmUe4hx0JhxQMDGTxs97Cy9IFI0n0NXuhVMSrQyhu8OLne31a3pKXXhClY5PwwgHFdwcncL52+MFryPFsMxDnIPOPLSzDU1rFH3LZuEKxkBECAcUvHtjFLHxmYLWiUioz3Ce3NeJKmfhoaW0FMMyFXEOOuN2OXBkXydOX4pjZm510bexqRTiE5JoZTShoB/MwMmewjqme+NJtNW70VovktBG0VhThUd2+XCyZwCZApJHb4xMSTEsExHnYADhoILJ1DzOFCD6tlDRSp6GDGWHrx57/Q0FP6VGRDbDFMJBBQPjM3jv5t1V20ZFNsNUxDkYwGeyom8FJPlERBLaNMJBBR/eGsOt0ZVF3zIZRq84B1M4tKcD1S5HQdUUI7EEHFIMyzTEORiA00F46kAn3rgyiORsesW20VgC3moX/I2SaGU0oazo2yo5D/1j05hMzYtzMIH6ajV59GTPwKrJo9F4AlukGJZpiHMwiHBQwcxcBq+vIvqW7YyWRCvj2dRSi3s2Na0aWvq4PrE8oZpBOKBgOJnC29dX1iWTYljmIs7BID69uRmdDZ4V1SeziVYi020eoYAflwYmcHVoedG3bD+Q1NYwh0d3t6POvbIu2czcPD4amZLwq4mIczAIh1ZP4GfRQYxP568nMJScxd2pOQlfmEgooKiibys47Wg8AaXRgwZJtDIFT5UTj+/twKkLMcwtE1q6NjSJ+QzLwA0TKco5EFELEZ0mol7tb3OeNo8S0Yc5nxki+oK27O+J6HrOsnuKscduZEXfXl1G9C0a0wr8iHMwjc5GD+7b2oLj55cXfVPrE8sxMZNQQMHY1Bx+0Tecd7nU8jafYt8cXgDwOjN3AXhd+/4JmPkMM9/DzPcAeAzAFIBXc5r8cXY5M39YpD22IrCxEZtbapetmftxFq6c8GYSDvjRN5hc2P+5pOcz6BtKytucyTy8qw0NnuV1yRaKYbVJMSyzKNY5PAvgRW36RQBfWKX9bwI4xczrLyBbQuSKvo3kEX3rjSfQUudGW71UtDKTowf8cBDy3og+Gp1CKp0R52Ay1S4njuzvxKsX8yePZothVTklEm4Wxe7pDmbOPhbHAHSs0v45AP+0aN43iOg8EX2LiJZNRyWiLxHRWSI6OzRUuG6R1YQCCuYzjJfzhJayoy9kpJK5tNVX48EdbXlF33olfGEZoYCC5GwaP4suvb6jgxLqM5tVnQMRvUZEF/J8ns1tx+pVtmwOPBH5ARwA8ErO7K8A2A3gPgAtAP5kufWZ+TvMfJCZD/p8vtXMtg17/F7s8NUteUplZkRjUu7QKsJBPz4amUJP/ydF3yKxJEgSrSzhwR2taKlzL7lWJmfTuDU6jW4ZxmoqqzoHZj7MzPvzfH4CIK7d9LM3/5X0In4bwI+ZeWHoDjMPsMosgL8DcH9x/479ICKEgwrevj6KwYmPRd8WEq3kacgSsqJvixPiovEEtrTUosYtiVZm43I6cHR/J16/PIip1MfJowvFsORBylSKDSsdA/C8Nv08gJ+s0PaLWBRSynEsBLW/4kKR9tiSUEBZIvomOjHW0lTrxsNdPpw4d+cTom+ReEIGCFhIOKhgem4er1/++DkzWwxLrhVzKdY5fBPA40TUC+Cw9h1EdJCIvpttRERbAWwC8LNF6/8jEfUA6AHQBuDfFWmPLdnZXo89i0TfFgT32uWEt4pw0I874zN4XxN9m03P4/rwpIT6LOS+rS3oaKj+xLUixbCsoSjnwMwjzHyImbu08NOoNv8sM/9hTrsbzLyBmTOL1n+MmQ9oYarfZebl01ZLnFDAj/dvjuH2XXWgVjSWQGeDB421kmhlFYf3dMDtciyElq4PS6KV1ai6ZH78NDqEiRk1Ai3FsKxBxoWZRDigAABOajeiiNQnthyvpwqPdauib/MZlgI/NiEcVJBKZ3D6oqpLFhWFXEsQ52ASm1trEdzYiBPn1RtR72BSRl/YgHBQwVBiFm9fH0E0noDLQdgmiVaWcu+mJmxoqsGJ83c+LoYlIoimI87BRMJBBT3943gzOoRUOiMdnzbgsd3tqHU7cfzcACKxJLa11cHtksvCSogIoaAfP+8dxjuaUqtcK+YjV4GJPK3VE/ir01EAEr6wAzVuJw7v6cDLFwZweWBCQn02IRxQkM4w/sMbfQDkWrECcQ4m4m+swX1bmxcSr7okrGQLQgE/7k7NoX9sWm5CNmGf0oBtbXXo6R+XYlgWIc7BZMJBtWN6c0stat0ui60RAOCRbh+8HvVYSMenPSAihLU37V2dXpGYsQBxDiZzdL8q+iY3IftQ7XLiib2dACCFl2xESHuQkmvFGuTR1WR83mr8aXifnPA2418+ugP+Rg+2SKKVbdjV4cUfP9mNR3aVjpZaOUHLFTyxMwcPHuSzZ89abYYgCEJJQUTvMfPBQtpKWEkQBEFYgjgHQRAEYQniHARBEIQliHMQBEEQliDOQRAEQViCOAdBEARhCeIcBEEQhCWIcxAEQRCWUJJJcEQ0BOCjPIvaAAybbM5aEPuKx+422t0+wP42in3Fs5yNW5i5oJTzknQOy0FEZwvN/rMCsa947G6j3e0D7G+j2Fc8etgoYSVBEARhCeIcBEEQhCWUm3P4jtUGrILYVzx2t9Hu9gH2t1HsK56ibSyrPgdBEARBH8rtzUEQBEHQAXEOgiAIwhJKzjkQ0W8R0UUiyhDRwUXLvkJEfUQUIaInl1l/GxG9rbX7ARG5DbT1B0T0ofa5QUQfLtPuBhH1aO1Mq2JERH9GRP05Nj61TLsj2j7tI6IXzLJP2/ZfEtEVIjpPRD8moqZl2pm6D1fbJ0RUrR3/Pu1822q0TTnb3kREZ4joknat/Os8bT5PROM5x/5rZtmXY8OKx4xU/i9tH54nok+ZaFt3zr75kIgmiOjfLGpj+j4kor8lokEiupAzr4WIThNRr/a3eZl1n9fa9BLR86tujJlL6gNgD4BuAD8FcDBn/l4A5wBUA9gG4CoAZ571fwjgOW36bwD8rybZ/X8C+Noyy24AaLNgX/4ZgP99lTZObV9uB+DW9vFeE218AoBLm/4LAH9h9T4sZJ8A+N8A/I02/RyAH5i4z/wAPqVNewFE89j3eQAnzD7n1nLMADwF4BQAAvAZAG9bZKcTQAxqApml+xDA5wB8CsCFnHn/HsAL2vQL+a4RAC0Arml/m7Xp5pW2VXJvDsx8mZkjeRY9C+D7zDzLzNcB9AG4P7cBERGAxwD8SJv1IoAvGGhu7nZ/G8A/Gb0tA7gfQB8zX2PmFIDvQ93XpsDMrzJzWvv6awAbzdr2ChSyT56Fen4B6vl2SDsPDIeZB5j5fW06AeAygA1mbFtnngXwX1jl1wCaiMhvgR2HAFxl5nyqDKbCzG8CGF00O/dcW+6e9iSA08w8ysx3AZwGcGSlbZWcc1iBDQBu5Xy/jaUXRCuAsZybTb42RvAwgDgz9y6znAG8SkTvEdGXTLAnly9rr+x/u8zraCH71Sx+H+qTZD7M3IeF7JOFNtr5Ng71/DMVLZx1L4C38yz+DSI6R0SniGifuZYBWP2Y2eXcew7LP9hZvQ8BoIOZB7TpGICOPG3WvC9d+timL0T0GoDOPIu+ysw/MduelSjQ1i9i5beGzzJzPxG1AzhNRFe0JwRD7QPw/wD4c6gX6Z9DDX39vh7bXQuF7EMi+iqANIB/XOZnDNuHpQoR1QP4bwD+DTNPLFr8PtQwSVLra/r/AHSZbKLtj5nWJ/kMgK/kWWyHffgJmJmJSJf8BFs6B2Y+vI7V+gFsyvm+UZuXywjUV1OX9jSXr82aWM1WInIB+B8BfHqF3+jX/g4S0Y+hhi10uUgK3ZdE9J8BnMizqJD9WhQF7MPfAxACcIi1AGqe3zBsH+ahkH2SbXNbOwcaoZ5/pkBEVVAdwz8y839fvDzXWTDzS0T0H4mojZlNE5Qr4JgZfu4VwFEA7zNzfPECO+xDjTgR+Zl5QAu7DeZp0w+1jyTLRqj9tstSTmGlYwCe00aJbIPqwd/JbaDdWM4A+E1t1vMAjH4TOQzgCjPfzreQiOqIyJudhtoBeyFfW71ZFL/9H5bZ7rsAukgd5eWG+op9zAz7AHVUEID/A8AzzDy1TBuz92Eh++QY1PMLUM+3N5ZzbHqj9W18D8BlZv6rZdp0ZvtAiOh+qPcCM51XIcfsGIB/po1a+gyA8ZzwiVks+9Zv9T7MIfdcW+6e9gqAJ4ioWQsfP6HNWx4ze9r1+EC9id0GMAsgDuCVnGVfhTqKJALgaM78lwAo2vR2qE6jD8B/BVBtsL1/D+BfLJqnAHgpx55z2uci1FCKWfvyHwD0ADivnWD+xfZp35+COuLlqpn2advugxor/VD7/M1iG63Yh/n2CYCvQ3ViAODRzq8+7XzbbuI++yzUUOH5nP32FIB/kT0XAXxZ21fnoHb0P2jycc17zBbZSAC+re3jHuSMTjTJxjqoN/vGnHmW7kOojmoAwJx2H/wDqH1ZrwPoBfAagBat7UEA381Z9/e187EPwD9fbVsinyEIgiAsoZzCSoIgCIJOiHMQBEEQliDOQRAEQViCOAdBEARhCeIcBEEQhCWIcxAEQRCWIM5BEARBWML/DzZAHa1LaBMfAAAAAElFTkSuQmCC\n",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"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": [
|
|
"First, let's set the [np.random.seed() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_np.png\">](https://docs.python.org/3/library/random.html#random.seed) to make the random numbers *replicable* on separate runs of this notebook."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 44,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"np.random.seed(42)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Then, 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": 45,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<matplotlib.collections.PathCollection at 0x7f008b235d00>"
|
|
]
|
|
},
|
|
"execution_count": 45,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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\n",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"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": "intro-to-data-science",
|
|
"language": "python",
|
|
"name": "intro-to-data-science"
|
|
},
|
|
"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.12.4"
|
|
},
|
|
"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
|
|
}
|